mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-09-12 18:06:11 +02:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36cf5856b5 | |||
| 01d1336cf0 | |||
| 28f2e9ea96 | |||
| 2d4e7f10c4 | |||
| aa1a5b8c36 | |||
| 43bdb68cbf | |||
| 8b43e331e3 | |||
| 302716fa61 | |||
| 188b6aba10 | |||
| 7af9cab688 | |||
| 714b88c638 | |||
| d9f1db10aa | |||
| bb10e1c9a3 | |||
| 264b6794f3 | |||
| a8b734c877 | |||
| 10ca77610e | |||
| c2eaea3665 | |||
| 1619f0ab6c | |||
| aba211221b | |||
| 81485baadb | |||
| 1b4fc38330 | |||
| 3571d9277d | |||
| e9b535d277 | |||
| 09ffd32144 | |||
| 27aa5c0343 | |||
| 1d95f9b224 | |||
| 4f1cb779ab | |||
| 758ddae344 | |||
| 14969b31d0 | |||
| d88e2eeb36 | |||
| 7946e69a66 | |||
| 15766f5266 | |||
| ed02845c40 | |||
| 4ffa0ffcb7 | |||
| c04c040713 | |||
| c763896b49 | |||
| e9a44f71b2 | |||
| 5078c8d910 | |||
| f9e0efb7ee | |||
| 926390508e | |||
| 45446c1c1d | |||
| b79c47cac9 | |||
| fd16e69464 | |||
| 92abf3e063 | |||
| 90a242a4aa | |||
| 1118c57d8f | |||
| eda9496479 | |||
| 0b94ff5adb | |||
| 62bf3ec021 | |||
| ab2268a927 | |||
| 1421627a47 | |||
| 02e5232bda | |||
| 289d03cfb2 | |||
| 965ab1abc4 | |||
| 06b2ff9a08 | |||
| b4a6606faf | |||
| def758580f | |||
| 5ea2b2ecc9 | |||
| b3886c6c47 | |||
| bc76220a5b | |||
| 60fa7946f5 | |||
| b6a703bd56 | |||
| 462c3b0e06 | |||
| 72138dbde5 | |||
| b2ea5d8f3e | |||
| 49080c5361 | |||
| 445dd94b53 | |||
| 7c03fc1550 | |||
| 06a8f12d6a | |||
| 8c7edf4d2d | |||
| 85b4679373 |
@@ -7,6 +7,8 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Be sure to read [FAQ](https://github.com/fastfetch-cli/fastfetch?tab=readme-ov-file#faq) before submitting a new issue.
|
||||
|
||||
<!-- We will try hard to solve the issue. However since platforms and hardwares vary greatly, it can be hard to find the root cause is. Providing following information may help us greatly. Thanks in advance -->
|
||||
|
||||
# General description of bug:
|
||||
@@ -74,10 +76,5 @@ Use `time fastfetch --stat` to show time usage for each module.
|
||||
|
||||
## If fastfetch behaves incorrectly on shell starting
|
||||
|
||||
<!-- NOTE for zsh / p10k users:
|
||||
There are known incompatibility between fastfetch and p10k instant prompt.
|
||||
The p10k doc clearly states that you should NOT print anything to stdout after p10k-instant-prompt is initialized.
|
||||
You should either put `fastfetch` before initialization of p10k-instant-prompt (recommended), remove it or use `fastfetch --pipe false` -->
|
||||
|
||||
* The bug is reproduceable with fresh / clean shell configuration (i.e. `fastfetch` is the single line of `.zshrc` or `~/.config/fish/config.fish`):
|
||||
* Does `sleep 1` before running `fastfetch` work?
|
||||
|
||||
@@ -484,7 +484,7 @@ jobs:
|
||||
with:
|
||||
msystem: CLANG32
|
||||
update: true
|
||||
install: git mingw-w64-clang-i686-7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd
|
||||
install: git p7zip mingw-w64-clang-i686-cmake mingw-w64-clang-i686-clang mingw-w64-clang-i686-vulkan-loader mingw-w64-clang-i686-vulkan-headers mingw-w64-clang-i686-opencl-icd
|
||||
|
||||
- name: print msys version
|
||||
run: uname -a
|
||||
|
||||
@@ -1,3 +1,49 @@
|
||||
# 2.13.1
|
||||
|
||||
Fix a regression introduced in v2.13.0
|
||||
|
||||
Bugfixes:
|
||||
* Fix CPU frequency not displayed if `bios_limit` is not available (CPU, Linux)
|
||||
|
||||
Features:
|
||||
* Add `--cpu-show-pe-core-count` to detect and display core count for performance / efficiency cores (CPU, FreeBSD)
|
||||
|
||||
# 2.13.0
|
||||
|
||||
Changes:
|
||||
* Option `--gpu-force-vulkan <?bool>` has been changed to `--gpu-detection-method <enum>`
|
||||
* Use `--gpu-detection-method vulkan` to get the old behavior
|
||||
* See `fastfetch -h gpu-detection-method` for detail
|
||||
* In Linux, BIOS limited CPU frequency is printed by default to match the behavior of neofetch (CPU, Linux, #947)
|
||||
|
||||
Features:
|
||||
* Add new module `Bootmgr` which prints information of stage 2 bootloader (grub, system-boot, etc)
|
||||
* Requires root permission to work on Windows and FreeBSD
|
||||
* Requires booting in UEFI mode
|
||||
* Add package manager lpkg and lpkg-build support (Packages, Linux)
|
||||
* Improve macOS 10.13 compatibility (macOS)
|
||||
* Detect core count for performance / efficiency cores (CPU)
|
||||
* Test it with `fastfetch -s cpu --cpu-format '{9}'`
|
||||
* Support min / max frequency and physical core count detection in FreeBSD, if kernel supports it (CPU, FreeBSD)
|
||||
* Detect DRM driver version if DRM detection method is used (GPU, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Don't detect `clifm` and `valgrind` as a terminal (Terminal, Linux)
|
||||
* Improve stability (PhysicalMemory, FreeBSD)
|
||||
* Fix bssid & status detection (Wifi, FreeBSD)
|
||||
* Ensure createTime is correctly initialized (Disk, FreeBSD / macOS)
|
||||
* Fix `--cpu-freq-ndigits` not working if `--cpu-format` is used
|
||||
* Fix `nix-user` package count detection (Packages, Linux)
|
||||
* Fix some memory leaks
|
||||
|
||||
Logos:
|
||||
* Fix Manjaro logo not displayed
|
||||
* Add SpoinkOS
|
||||
* Add Loc-OS
|
||||
* Add Furreto Linux
|
||||
* Fix TorizonCore logo colors
|
||||
* Fix KDE neon logo not displayed
|
||||
|
||||
# 2.12.0
|
||||
|
||||
Changes:
|
||||
@@ -20,6 +66,7 @@ Features:
|
||||
* Add option `--localip-show-all-ips` to show all IPs assigned to the same interface (LocalIP)
|
||||
* Default to `false`
|
||||
* Improve compatibility with `(*term)` (#909, Terminal, macOS)
|
||||
* Support GPU core count and frequency detection for Asahi Linux (GPU, Linux)
|
||||
|
||||
Bugfixes:
|
||||
* Rename option `--temperature-unit` to `--temp-unit` as documented in help messages
|
||||
|
||||
+9
-2
@@ -1,7 +1,7 @@
|
||||
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
|
||||
|
||||
project(fastfetch
|
||||
VERSION 2.12.0
|
||||
VERSION 2.13.1
|
||||
LANGUAGES C
|
||||
DESCRIPTION "Fast neofetch-like system information tool"
|
||||
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
|
||||
@@ -115,7 +115,7 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--tsaware -Wl,--build-id -Wl,--subsystem,console:6.1,--major-os-version,6,--minor-os-version,1")
|
||||
elseif(APPLE)
|
||||
elseif(APPLE AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-arc")
|
||||
endif()
|
||||
|
||||
@@ -284,6 +284,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/common/properties.c
|
||||
src/common/settings.c
|
||||
src/common/temps.c
|
||||
src/detection/bootmgr/bootmgr.c
|
||||
src/detection/chassis/chassis.c
|
||||
src/detection/cpu/cpu.c
|
||||
src/detection/cpuusage/cpuusage.c
|
||||
@@ -314,6 +315,7 @@ set(LIBFASTFETCH_SRC
|
||||
src/modules/bios/bios.c
|
||||
src/modules/bluetooth/bluetooth.c
|
||||
src/modules/board/board.c
|
||||
src/modules/bootmgr/bootmgr.c
|
||||
src/modules/brightness/brightness.c
|
||||
src/modules/break/break.c
|
||||
src/modules/camera/camera.c
|
||||
@@ -394,6 +396,7 @@ if(LINUX)
|
||||
src/detection/battery/battery_linux.c
|
||||
src/detection/bios/bios_linux.c
|
||||
src/detection/board/board_linux.c
|
||||
src/detection/bootmgr/bootmgr_linux.c
|
||||
src/detection/brightness/brightness_linux.c
|
||||
src/detection/chassis/chassis_linux.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
@@ -462,6 +465,7 @@ elseif(ANDROID)
|
||||
src/detection/bios/bios_android.c
|
||||
src/detection/bluetooth/bluetooth_nosupport.c
|
||||
src/detection/board/board_android.c
|
||||
src/detection/bootmgr/bootmgr_nosupport.c
|
||||
src/detection/brightness/brightness_nosupport.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/cpu/cpu_linux.c
|
||||
@@ -520,6 +524,7 @@ elseif(BSD)
|
||||
src/detection/bios/bios_bsd.c
|
||||
src/detection/bluetooth/bluetooth_linux.c
|
||||
src/detection/board/board_bsd.c
|
||||
src/detection/bootmgr/bootmgr_bsd.c
|
||||
src/detection/brightness/brightness_bsd.c
|
||||
src/detection/chassis/chassis_bsd.c
|
||||
src/detection/cpu/cpu_bsd.c
|
||||
@@ -588,6 +593,7 @@ elseif(APPLE)
|
||||
src/detection/bios/bios_apple.c
|
||||
src/detection/bluetooth/bluetooth_apple.m
|
||||
src/detection/board/board_apple.c
|
||||
src/detection/bootmgr/bootmgr_apple.c
|
||||
src/detection/brightness/brightness_apple.c
|
||||
src/detection/chassis/chassis_nosupport.c
|
||||
src/detection/cpu/cpu_apple.c
|
||||
@@ -647,6 +653,7 @@ elseif(WIN32)
|
||||
src/detection/bios/bios_windows.c
|
||||
src/detection/bluetooth/bluetooth_windows.c
|
||||
src/detection/board/board_windows.c
|
||||
src/detection/bootmgr/bootmgr_windows.c
|
||||
src/detection/brightness/brightness_windows.cpp
|
||||
src/detection/chassis/chassis_windows.c
|
||||
src/detection/cpu/cpu_windows.c
|
||||
|
||||
@@ -101,11 +101,90 @@ Logos can be heavily customized too; see the [logo documentation](https://github
|
||||
|
||||
## FAQ
|
||||
|
||||
Q: Why do you need a very performant version of neofetch?
|
||||
> I like putting neofetch in my ~/.bashrc to have a system overview whenever I use the terminal, but the slow speed annoyed me, so I created this. Also neofetch didn't output everything correctly (e.g Font is displayed as "[Plasma], Noto Sans, 10 [GTK2/3]") and writing my own tool gave me the possibility to fine tune it to run perfectly on at least my configuration.
|
||||
### Q: Neofetch is good enough. Why do I need fastfetch?
|
||||
|
||||
Q: It does not display [*] correctly for me, what can I do?
|
||||
> This is most likely because your system is not implemented (yet). At the moment I am focusing more on making the core app better, than adding more configurations. Feel free to open a pull request if you want to add support for your configuration
|
||||
1. Fastfetch is actively maintained.
|
||||
2. Fastfetch is faster. As the name suggests.
|
||||
3. Fastfetch is more feature-rich. By default fastfetch only has a few modules enabled. Use `fastfetch -c all` to find what you want.
|
||||
4. Fastfetch is more configurable. You can find more information in the Wiki: <https://github.com/fastfetch-cli/fastfetch/wiki/Configuration>
|
||||
5. Fastfetch is more polished. For example, neofetch prints `555MiB` in `Memory` module and `23G` in `Disk` module (notibily the difference of `MiB` and `G`), while fastfetch prints `555.00 MiB` and `22.97 GiB` respectively.
|
||||
6. Fastfetch is more accurate. For example, [neofetch never actually supports Wayland protocol](https://github.com/dylanaraps/neofetch/pull/2395).
|
||||
|
||||
### Q: Fastfetch shows my local IP address. It leaks my privacy!
|
||||
|
||||
A local IP (10.x.x.x, 172.x.x.x, 192.168.x.x) has nothing to do with privacy. It only makes sense if you are on the same network, for example, if you connect to the same Wi-Fi network.
|
||||
|
||||
Actually the `Local IP` module is the most useful module for me personally. I (@CarterLi) have several VMs installed to test fastfetch and often need to SSH into them. I have fastfetch running on shell startup and I never need to type `ip addr` manually.
|
||||
|
||||
If you really don't like it, you can disable the `Local IP` module in `config.jsonc`.
|
||||
|
||||
### Q: Where is the config file? I can't find it.
|
||||
|
||||
`Fastfetch` don't generate config file automatically. You can use `fastfetch --gen-config` to generate one. The config file will be saved in `~/.config/fastfetch/config.jsonc` by default. See [Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration).
|
||||
|
||||
### Q: The configuration is so complex. Where is the documentation?
|
||||
|
||||
Fastfetch uses JSON (with comments) for configuration. I suggest you use an IDE with JSON schema support (like VSCode) to edit it.
|
||||
|
||||
Alternatively, you can refer to the presets in [`presets` directory](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets).
|
||||
|
||||
### Q: I WANT THE DOCUMENTATION!
|
||||
|
||||
[Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema). It is generated from [JSON schema](https://github.com/fastfetch-cli/fastfetch/blob/dev/doc/json_schema.json) but you won't like it.
|
||||
|
||||
### Q: How can I customize the module output?
|
||||
|
||||
Fastfetch uses `format` to generate output. For example to make `GPU` module show GPU name only and ignore other information, you can use
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"type": "gpu",
|
||||
"format": "{2}" // See `fastfetch -h gpu-format` for detail
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
which is equivalent to `fastfetch -s gpu --gpu-format '{2}'`
|
||||
|
||||
See `fastfetch -h format` for basic usage. For module specific formattion, see `fastfetch -h <module>-format`
|
||||
|
||||
### Q: I have my own ascii-art / image file. How can I show it with fastfetch?
|
||||
|
||||
Try `fastfetch -l /path/to/logo`. See [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for detail.
|
||||
|
||||
### Q: Fastfetch runs in white and black on shell startup. Why?
|
||||
|
||||
This issue usually happens when using fastfetch with `p10k`. There are known incompatibility between fastfetch and p10k instant prompt.
|
||||
The p10k doc clearly states that you should NOT print anything to stdout after `p10k-instant-prompt` is initialized. You should either put `fastfetch` before initialization of `p10k-instant-prompt` (recommended)
|
||||
|
||||
You can always use `fastfetch --pipe false` to force fastfetch running in colorful mode.
|
||||
|
||||
### 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:
|
||||
|
||||
```jsonc
|
||||
// This module shows the default editor
|
||||
{
|
||||
"modules": [
|
||||
{
|
||||
"type": "command",
|
||||
"text": "$EDITOR --version | head -1",
|
||||
"key": "Editor"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Otherwise, open a feature request in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues).
|
||||
|
||||
### Q: I have questions. Where can I get help?
|
||||
|
||||
* 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.
|
||||
|
||||
## Star History
|
||||
|
||||
|
||||
+1
-1
@@ -197,7 +197,7 @@ __fastfetch_completion()
|
||||
"--disk-show-subvolumes"
|
||||
"--gpu-hide-integrated"
|
||||
"--gpu-hide-discrete"
|
||||
"--gpu-force-vulkan"
|
||||
"--gpu-force-method"
|
||||
"--disk-show-unknown"
|
||||
"--bluetooth-show-disconnected"
|
||||
)
|
||||
|
||||
+1
-2
@@ -85,8 +85,7 @@ string match -r -a -g "^###> ?(.*)" < (status -f) | string collect | python3 | s
|
||||
###> elif type == 'config':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_config)"')
|
||||
###> elif type == 'enum':
|
||||
###> temp: str = ' '.join(map(lambda x: f"{x[0]}\\t{x[1]}", flag["arg"]["enum"].items()))
|
||||
###> print(f'{command_prefix} -x -a "{temp}"')
|
||||
###> print(f'{command_prefix} -x -a "{' '.join(flag["arg"]["enum"])}"')
|
||||
###> elif type == 'logo':
|
||||
###> print(f'{command_prefix} -x -a "(__fastfetch_complete_logo)"')
|
||||
###> elif type == 'structure':
|
||||
|
||||
+26
-5
@@ -680,6 +680,7 @@
|
||||
"bios",
|
||||
"bluetooth",
|
||||
"board",
|
||||
"bootmgr",
|
||||
"break",
|
||||
"brightness",
|
||||
"camera",
|
||||
@@ -713,6 +714,7 @@
|
||||
"os",
|
||||
"packages",
|
||||
"physicaldisk",
|
||||
"physicalmemory",
|
||||
"player",
|
||||
"poweradapter",
|
||||
"processes",
|
||||
@@ -771,12 +773,16 @@
|
||||
"anyOf": [
|
||||
{
|
||||
"const": "bios",
|
||||
"description": "Print BIOS name, version, release date, etc"
|
||||
"description": "Print information of 1st-stage bootloader (name, version, release date, etc)"
|
||||
},
|
||||
{
|
||||
"const": "board",
|
||||
"description": "Print mather board name and other info"
|
||||
},
|
||||
{
|
||||
"const": "bootmgr",
|
||||
"description": "Print information of 2nd-stage bootloader (name, firmware, etc)"
|
||||
},
|
||||
{
|
||||
"const": "camera",
|
||||
"description": "Print available cameras"
|
||||
@@ -829,6 +835,10 @@
|
||||
"const": "os",
|
||||
"description": "Print operating system name and version"
|
||||
},
|
||||
{
|
||||
"const": "physicalmemory",
|
||||
"description": "Print system physical memory devices"
|
||||
},
|
||||
{
|
||||
"const": "player",
|
||||
"description": "Print music player name"
|
||||
@@ -1064,6 +1074,11 @@
|
||||
"maximum": 9,
|
||||
"default": 2
|
||||
},
|
||||
"showPeCoreCount": {
|
||||
"description": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"key": {
|
||||
"$ref": "#/$defs/key"
|
||||
},
|
||||
@@ -1445,10 +1460,16 @@
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"forceVulkan": {
|
||||
"description": "Force using vulkan to detect GPUs, which support video memory usage detection with `--allow-slow-operations`",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
"detectionMethod": {
|
||||
"description": "Force using a specified method to detect GPUs",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"auto",
|
||||
"pci",
|
||||
"vulkan",
|
||||
"opengl"
|
||||
],
|
||||
"default": "auto"
|
||||
},
|
||||
"hideType": {
|
||||
"description": "Specify the type of GPUs should not be printed",
|
||||
|
||||
@@ -9,6 +9,7 @@ static FFModuleBaseInfo* B[] = {
|
||||
(void*) &instance.config.modules.bios,
|
||||
(void*) &instance.config.modules.bluetooth,
|
||||
(void*) &instance.config.modules.board,
|
||||
(void*) &instance.config.modules.bootmgr,
|
||||
(void*) &instance.config.modules.break_,
|
||||
(void*) &instance.config.modules.brightness,
|
||||
NULL,
|
||||
|
||||
+20
-6
@@ -1152,6 +1152,15 @@
|
||||
"default": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "cpu-show-pe-core-count",
|
||||
"desc": "Detect and display CPU frequency of different core types (eg. Pcore and Ecore) if supported",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "cpuusage-separate",
|
||||
"desc": "Display CPU usage per CPU logical core, instead of an average result",
|
||||
@@ -1197,13 +1206,18 @@
|
||||
}
|
||||
},
|
||||
{
|
||||
"long": "gpu-force-vulkan",
|
||||
"desc": "Force using vulkan to detect GPUs",
|
||||
"remark": "Vulkan supports video memory usage detection",
|
||||
"long": "gpu-detection-method",
|
||||
"desc": "Force using a specified method to detect GPUs",
|
||||
"remark": "Methods are used in this order: DRM (Linux only) -> PCI (Linux, FreeBSD and other platform specific methods) -> Vulkan -> OpenGL",
|
||||
"arg": {
|
||||
"type": "bool",
|
||||
"optional": true,
|
||||
"default": false
|
||||
"type": "enum",
|
||||
"enum": {
|
||||
"auto": "Use DRM if available, which is most feature-rich. Requires proper DRM driver installed",
|
||||
"pci": "Search PCI devices, which do not requires any driver installed",
|
||||
"vulkan": "Use Vulkan API. Slow and requires vulkan driver installed",
|
||||
"opengl": "Use OpenGL API. Slow and only detects one GPU"
|
||||
},
|
||||
"default": "auto"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "battery.h"
|
||||
|
||||
#include "common/io/io.h"
|
||||
#include "util/windows/nt.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
@@ -12,16 +13,6 @@
|
||||
#include <devguid.h>
|
||||
#include <winternl.h>
|
||||
|
||||
NTSYSCALLAPI
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
NtPowerInformation(
|
||||
IN POWER_INFORMATION_LEVEL InformationLevel,
|
||||
IN PVOID InputBuffer OPTIONAL,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength);
|
||||
|
||||
static inline void wrapSetupDiDestroyDeviceInfoList(HDEVINFO* hdev)
|
||||
{
|
||||
if(*hdev)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
const char* ffDetectBios(FFBiosResult* bios)
|
||||
const char *ffDetectBios(FFBiosResult *bios)
|
||||
{
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date);
|
||||
ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_release", "/sys/class/dmi/id/bios_release", &bios->release);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "bios.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
#include "util/windows/registry.h"
|
||||
|
||||
#include <ntstatus.h>
|
||||
#include <winternl.h>
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "efi_helper.h"
|
||||
|
||||
static inline uint8_t evBits(uint16_t val, uint8_t mask, uint8_t shift)
|
||||
{
|
||||
return (uint8_t) ((val & (mask << shift)) >> shift);
|
||||
}
|
||||
|
||||
static void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result)
|
||||
{
|
||||
for (uint32_t i = 0; chars[i]; i++)
|
||||
{
|
||||
if (chars[i] <= 0x007f)
|
||||
ffStrbufAppendC(result, (char) chars[i]);
|
||||
else if (chars[i] > 0x007f && chars[i] <= 0x07ff)
|
||||
{
|
||||
ffStrbufAppendC(result, (char) (0xc0 | evBits(chars[i], 0x1f, 6)));
|
||||
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 0)));
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufAppendC(result, (char) (0xe0 | evBits(chars[i], 0xf, 12)));
|
||||
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 6)));
|
||||
ffStrbufAppendC(result, (char) (0x80 | evBits(chars[i], 0x3f, 0)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* result)
|
||||
{
|
||||
uint32_t descLen = 0;
|
||||
while (efiOption->Description[descLen]) ++descLen;
|
||||
|
||||
if (descLen)
|
||||
ffEfiUcs2ToUtf8(efiOption->Description, &result->name);
|
||||
|
||||
for (
|
||||
ffEfiDevicePathProtocol* filePathList = (void*) &efiOption->Description[descLen + 1];
|
||||
filePathList->Type != 0x7F; // End of Hardware Device Path
|
||||
filePathList = (void*) ((uint8_t*) filePathList + filePathList->Length))
|
||||
{
|
||||
if (filePathList->Type == 4 && filePathList->SubType == 4)
|
||||
{
|
||||
// https://uefi.org/specs/UEFI/2.10/10_Protocols_Device_Path_Protocol.html#file-path-media-device-path
|
||||
ffEfiUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, &result->firmware);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
typedef struct FFBootmgrResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
FFstrbuf firmware;
|
||||
bool secureBoot;
|
||||
} FFBootmgrResult;
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* bios);
|
||||
@@ -0,0 +1,12 @@
|
||||
#include "bootmgr.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
if (ffPathExists("/System/Library/CoreServices/boot.efi", FF_PATHTYPE_FILE))
|
||||
ffStrbufSetStatic(&result->firmware, "/System/Library/CoreServices/boot.efi");
|
||||
|
||||
ffStrbufSetStatic(&result->name, "iBoot");
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
#include "bootmgr.h"
|
||||
#include "efi_helper.h"
|
||||
#include "common/io/io.h"
|
||||
|
||||
#include <sys/efiio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
FF_AUTO_CLOSE_FD int efifd = open("/dev/efi", O_RDWR);
|
||||
if (efifd < 0) return "open(/dev/efi) failed";
|
||||
|
||||
uint8_t buffer[2048];
|
||||
struct efi_var_ioc ioc = {
|
||||
.vendor = { 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, { 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c } },
|
||||
.data = buffer,
|
||||
};
|
||||
|
||||
ioc.datasize = sizeof(buffer);
|
||||
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', 'C', 'u', 'r', 'r', 'e', 'n', 't', '\0' };
|
||||
ioc.namesize = sizeof("BootCurrent") * 2;
|
||||
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2)
|
||||
return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed";
|
||||
|
||||
unsigned char hex[5];
|
||||
snprintf((char*) hex, sizeof(hex), "%04X", *(uint16_t*)buffer);
|
||||
ioc.datasize = sizeof(buffer);
|
||||
ioc.name = (efi_char[]){ 'B', 'o', 'o', 't', hex[0], hex[1], hex[2], hex[3], '\0' };
|
||||
ioc.namesize = sizeof("Boot####") * 2;
|
||||
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize == sizeof(buffer))
|
||||
return "ioctl(EFIIOC_VAR_GET, Boot####) failed";
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
|
||||
|
||||
ioc.name = (efi_char[]){ 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', '\0' };
|
||||
ioc.namesize = sizeof("SecureBoot") * 2;
|
||||
ioc.datasize = sizeof(buffer);
|
||||
if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) == 0 && ioc.datasize == 1)
|
||||
result->secureBoot = !!buffer[0];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "bootmgr.h"
|
||||
#include "common/io/io.h"
|
||||
#include "efi_helper.h"
|
||||
|
||||
#define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/"
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
uint8_t buffer[2048];
|
||||
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "BootCurrent-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6)
|
||||
return "Failed to read efivar: BootCurrent";
|
||||
|
||||
uint16_t value = *(uint16_t *)&buffer[4];
|
||||
snprintf((char*) buffer, sizeof(buffer), FF_EFIVARS_PATH_PREFIX "Boot%04X-" FF_EFI_GLOBAL_GUID, value);
|
||||
|
||||
ssize_t size = ffReadFileData((const char*) buffer, sizeof(buffer), buffer);
|
||||
if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer))
|
||||
return "Failed to read efivar: Boot####";
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)&buffer[4], result);
|
||||
|
||||
if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) == 6)
|
||||
result->secureBoot = buffer[4] == 1;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "bootmgr.h"
|
||||
|
||||
const char* ffDetectBootmgr(FF_MAYBE_UNUSED FFBootmgrResult* result)
|
||||
{
|
||||
return "Not supported on this platform";
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "bootmgr.h"
|
||||
#include "efi_helper.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
const char* enablePrivilege(const wchar_t* privilege)
|
||||
{
|
||||
HANDLE token;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token))
|
||||
return "OpenProcessToken() failed";
|
||||
|
||||
TOKEN_PRIVILEGES tp = {
|
||||
.PrivilegeCount = 1,
|
||||
.Privileges = {
|
||||
(LUID_AND_ATTRIBUTES) { .Attributes = SE_PRIVILEGE_ENABLED }
|
||||
},
|
||||
};
|
||||
if (!LookupPrivilegeValueW(NULL, privilege, &tp.Privileges[0].Luid))
|
||||
return "LookupPrivilegeValue() failed";
|
||||
|
||||
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(tp), NULL, NULL))
|
||||
return "AdjustTokenPrivileges() failed";
|
||||
|
||||
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
|
||||
return "The token does not have the specified privilege";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectBootmgr(FFBootmgrResult* result)
|
||||
{
|
||||
if (enablePrivilege(L"SeSystemEnvironmentPrivilege") != NULL)
|
||||
return "Failed to enable SeSystemEnvironmentPrivilege";
|
||||
|
||||
uint16_t value;
|
||||
if (GetFirmwareEnvironmentVariableW(L"BootCurrent", L"{" FF_EFI_GLOBAL_GUID L"}", &value, sizeof(value)) != 2)
|
||||
return "GetFirmwareEnvironmentVariableW(BootCurrent) failed";
|
||||
|
||||
uint8_t buffer[2048];
|
||||
wchar_t key[16];
|
||||
wsprintfW(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";
|
||||
|
||||
ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result);
|
||||
|
||||
DWORD uefiSecureBootEnabled = 0, bufSize = 0;
|
||||
if (RegGetValueW(HKEY_LOCAL_MACHINE, L"SYSTEM\\ControlSet001\\Control\\SecureBoot\\State", L"UEFISecureBootEnabled", RRF_RT_REG_DWORD, NULL, &uefiSecureBootEnabled, &bufSize) == ERROR_SUCCESS)
|
||||
result->secureBoot = !!uefiSecureBootEnabled;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "bootmgr.h"
|
||||
|
||||
// https://uefi.org/specs/UEFI/2.10/10_Protocols_Device_Path_Protocol.html#generic-device-path-structures
|
||||
typedef struct ffEfiDevicePathProtocol
|
||||
{
|
||||
uint8_t Type;
|
||||
uint8_t SubType;
|
||||
uint16_t Length;
|
||||
uint8_t SpecificDevicePathData[];
|
||||
} ffEfiDevicePathProtocol;
|
||||
|
||||
// https://uefi.org/specs/UEFI/2.10/03_Boot_Manager.html#load-options
|
||||
typedef struct FFEfiLoadOption
|
||||
{
|
||||
uint32_t Attributes;
|
||||
uint16_t FilePathListLength;
|
||||
uint16_t Description[];
|
||||
// ffEfiDevicePathProtocol FilePathList[];
|
||||
// uint8_t OptionalData[];
|
||||
} FFEfiLoadOption;
|
||||
|
||||
bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* result);
|
||||
|
||||
#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c"
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
const char* ffDetectCamera(FFlist* result)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
FF_SUPPRESS_IO(); // #822
|
||||
|
||||
AVCaptureDeviceType deviceType;
|
||||
@@ -47,6 +48,8 @@ const char* ffDetectCamera(FFlist* result)
|
||||
camera->width = size.width < 0 ? 0 : (uint32_t) size.width;
|
||||
camera->height = size.height < 0 ? 0 : (uint32_t) size.height;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
#else
|
||||
return "No support for old MacOS version";
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
|
||||
#define FF_CPU_TEMP_UNSET (0/0.0)
|
||||
|
||||
typedef struct FFCPUCore
|
||||
{
|
||||
uint32_t freq;
|
||||
uint32_t count;
|
||||
} FFCPUCore;
|
||||
|
||||
typedef struct FFCPUResult
|
||||
{
|
||||
FFstrbuf name;
|
||||
@@ -16,10 +22,12 @@ typedef struct FFCPUResult
|
||||
double frequencyBase; // GHz
|
||||
double frequencyMax; // GHz
|
||||
double frequencyMin; // GHz
|
||||
double frequencyBiosLimit; // GHz
|
||||
|
||||
FFCPUCore coreTypes[16]; // number of P cores, E cores, etc.
|
||||
|
||||
double temperature;
|
||||
} FFCPUResult;
|
||||
|
||||
const char* ffCPUDetectByCpuid(FFCPUResult* cpu);
|
||||
const char* ffDetectCPU(const FFCPUOptions* options, FFCPUResult* cpu);
|
||||
const char* ffCPUAppleCodeToName(uint32_t code);
|
||||
|
||||
@@ -68,20 +68,37 @@ static const char* detectFrequency(FFCPUResult* cpu)
|
||||
{
|
||||
cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0);
|
||||
if(cpu->frequencyMax > 0.0)
|
||||
cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0;
|
||||
else
|
||||
cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000.0 / 1000.0 / 1000.0;
|
||||
if(cpu->frequencyBase != cpu->frequencyBase)
|
||||
{
|
||||
unsigned current = 0;
|
||||
size_t size = sizeof(current);
|
||||
if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0)
|
||||
cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0;
|
||||
cpu->frequencyBase = (double) current / 1000.0 / 1000.0 / 1000.0;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectCoreCount(FFCPUResult* cpu)
|
||||
{
|
||||
uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0);
|
||||
if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed";
|
||||
|
||||
char sysctlKey[] = "hw.perflevelN.logicalcpu";
|
||||
if (nPerfLevels > sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]))
|
||||
nPerfLevels = sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]);
|
||||
for (uint32_t i = 0; i < nPerfLevels; ++i)
|
||||
{
|
||||
sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i);
|
||||
cpu->coreTypes[i] = (FFCPUCore) {
|
||||
.freq = nPerfLevels - i,
|
||||
.count = (uint32_t) ffSysctlGetInt(sysctlKey, 0),
|
||||
};
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
{
|
||||
if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL)
|
||||
@@ -104,6 +121,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) ffSysctlGetInt("hw.activecpu", 1);
|
||||
|
||||
detectFrequency(cpu);
|
||||
if (options->showPeCoreCount) detectCoreCount(cpu);
|
||||
|
||||
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
|
||||
|
||||
|
||||
@@ -11,6 +11,64 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresLogical = cpu->coresPhysical;
|
||||
cpu->coresOnline = cpu->coresPhysical;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
|
||||
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0)
|
||||
{
|
||||
// <groups>
|
||||
// <group level="1" cache-level="3">
|
||||
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
|
||||
// <children>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// <group level="2" cache-level="2">
|
||||
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
|
||||
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
|
||||
// </group>
|
||||
// </children>
|
||||
// </group>
|
||||
// </groups>
|
||||
uint32_t i = 0;
|
||||
while (true)
|
||||
{
|
||||
i = ffStrbufNextIndexS(&buffer, i, "<flag name=\"THREAD\">THREAD group</flag>"); // Find physical core with hyper-threading enabled
|
||||
if (i >= buffer.length) break;
|
||||
cpu->coresPhysical--;
|
||||
i += (uint32_t) strlen("<flag name=\"THREAD\">THREAD group</flag>");
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
|
||||
{
|
||||
ffStrbufClear(&buffer);
|
||||
char key[32];
|
||||
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
|
||||
if (ffSysctlGetString(key, &buffer) == NULL && buffer.length > 0)
|
||||
{
|
||||
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
|
||||
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
|
||||
uint32_t fmin = fmax;
|
||||
uint32_t i = ffStrbufLastIndexC(&buffer, ' ');
|
||||
if (i < buffer.length)
|
||||
fmin = (uint32_t) strtoul(buffer.chars + i + 1, NULL, 10);
|
||||
if (!(cpu->frequencyMin <= fmin)) cpu->frequencyMin = fmin; // Counting for NaN
|
||||
if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax;
|
||||
|
||||
if (options->showPeCoreCount)
|
||||
{
|
||||
uint32_t ifreq = 0;
|
||||
while (cpu->coreTypes[ifreq].freq != fmax && cpu->coreTypes[ifreq].freq > 0)
|
||||
++ifreq;
|
||||
if (cpu->coreTypes[ifreq].freq == 0)
|
||||
cpu->coreTypes[ifreq].freq = fmax;
|
||||
cpu->coreTypes[ifreq].count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
cpu->frequencyMin /= 1000;
|
||||
cpu->frequencyMax /= 1000;
|
||||
|
||||
int clockRate = ffSysctlGetInt("hw.clockrate", 0);
|
||||
cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0;
|
||||
cpu->temperature = FF_CPU_TEMP_UNSET;
|
||||
|
||||
@@ -88,14 +88,14 @@ static const char* parseCpuInfo(FFCPUResult* cpu, FFstrbuf* physicalCoresBuffer,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
|
||||
static uint32_t getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, const char* scalingFileName, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t baseLen = basePath->length;
|
||||
ffStrbufAppendS(basePath, cpuinfoFileName);
|
||||
bool ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
return (uint32_t) ffStrbufToUInt(buffer, 0);
|
||||
|
||||
if (scalingFileName)
|
||||
{
|
||||
@@ -103,13 +103,31 @@ static double getFrequency(FFstrbuf* basePath, const char* cpuinfoFileName, cons
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return ffStrbufToDouble(buffer) / 1e6;
|
||||
return (uint32_t) ffStrbufToUInt(buffer, 0);
|
||||
}
|
||||
|
||||
return 0.0/0.0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool detectFrequency(FFCPUResult* cpu)
|
||||
static uint8_t getNumCores(FFstrbuf* basePath, FFstrbuf* buffer)
|
||||
{
|
||||
uint32_t baseLen = basePath->length;
|
||||
ffStrbufAppendS(basePath, "/affected_cpus");
|
||||
bool ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return (uint8_t) ffStrbufCountC(buffer, ' ') + 1;
|
||||
|
||||
ffStrbufAppendS(basePath, "/related_cpus");
|
||||
ok = ffReadFileBuffer(basePath->chars, buffer);
|
||||
ffStrbufSubstrBefore(basePath, baseLen);
|
||||
if (ok)
|
||||
return (uint8_t) ffStrbufCountC(buffer, ' ') + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options)
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateS("/sys/devices/system/cpu/cpufreq/");
|
||||
FF_AUTO_CLOSE_DIR DIR* dir = opendir(path.chars);
|
||||
@@ -119,38 +137,61 @@ static bool detectFrequency(FFCPUResult* cpu)
|
||||
uint32_t baseLen = path.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dir)) != NULL)
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
if (ffStrStartsWith(entry->d_name, "policy") && isdigit(entry->d_name[strlen("policy")]))
|
||||
{
|
||||
ffStrbufAppendS(&path, entry->d_name);
|
||||
double fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
|
||||
if (fbase == fbase)
|
||||
uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer);
|
||||
if (fbase > 0)
|
||||
{
|
||||
if (cpu->frequencyBase == cpu->frequencyBase)
|
||||
cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase;
|
||||
else
|
||||
cpu->frequencyBase = fbase;
|
||||
}
|
||||
double fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
if (fmax == fmax)
|
||||
uint32_t fbioslimit = getFrequency(&path, "/bios_limit", NULL, &buffer);
|
||||
if (fbioslimit > 0)
|
||||
{
|
||||
if (cpu->frequencyBiosLimit == cpu->frequencyBiosLimit)
|
||||
cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit;
|
||||
else
|
||||
cpu->frequencyBiosLimit = fbioslimit;
|
||||
}
|
||||
uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer);
|
||||
if (fmax > 0)
|
||||
{
|
||||
if (cpu->frequencyMax == cpu->frequencyMax)
|
||||
cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax;
|
||||
else
|
||||
cpu->frequencyMax = fmax;
|
||||
}
|
||||
double fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
|
||||
if (fmin == fmin)
|
||||
uint32_t fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer);
|
||||
if (fmin > 0)
|
||||
{
|
||||
if (cpu->frequencyMin == cpu->frequencyMin)
|
||||
cpu->frequencyMin = cpu->frequencyMin < fmin ? cpu->frequencyMin : fmin;
|
||||
else
|
||||
cpu->frequencyMin = fmin;
|
||||
}
|
||||
|
||||
if (options->showPeCoreCount)
|
||||
{
|
||||
uint32_t freq = fbase == 0 ? fmax : fbase; // seems base frequencies are more stable
|
||||
uint32_t ifreq = 0;
|
||||
while (cpu->coreTypes[ifreq].freq != freq && cpu->coreTypes[ifreq].freq > 0)
|
||||
++ifreq;
|
||||
if (cpu->coreTypes[ifreq].freq == 0)
|
||||
cpu->coreTypes[ifreq].freq = freq;
|
||||
cpu->coreTypes[ifreq].count += getNumCores(&path, &buffer);
|
||||
}
|
||||
ffStrbufSubstrBefore(&path, baseLen);
|
||||
}
|
||||
}
|
||||
cpu->frequencyBase /= 1e6;
|
||||
cpu->frequencyMax /= 1e6;
|
||||
cpu->frequencyMin /= 1e6;
|
||||
cpu->frequencyBiosLimit /= 1e6;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -232,7 +273,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
cpu->coresOnline = (uint16_t) get_nprocs();
|
||||
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, cpu->coresLogical);
|
||||
|
||||
if (!detectFrequency(cpu) || cpu->frequencyBase != cpu->frequencyBase)
|
||||
if (!detectFrequency(cpu, options) || cpu->frequencyBase != cpu->frequencyBase)
|
||||
cpu->frequencyBase = ffStrbufToDouble(&cpuMHz) / 1000;
|
||||
|
||||
if(cpuUarch.length > 0)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "cpu.h"
|
||||
#include "detection/temps/temps_windows.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/windows/nt.h"
|
||||
#include "util/mallocHelper.h"
|
||||
#include "util/smbiosHelper.h"
|
||||
|
||||
@@ -146,13 +147,6 @@ static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
if(!ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", &hKey, NULL))
|
||||
return "ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, L\"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\", &hKey, NULL) failed";
|
||||
|
||||
if (detectSpeedByCpuid(cpu) != NULL || cpu->frequencyBase != cpu->frequencyBase)
|
||||
{
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
cpu->frequencyBase = mhz / 1000.0;
|
||||
}
|
||||
|
||||
ffRegReadStrbuf(hKey, L"ProcessorNameString", &cpu->name, NULL);
|
||||
ffRegReadStrbuf(hKey, L"VendorIdentifier", &cpu->vendor, NULL);
|
||||
|
||||
@@ -163,6 +157,31 @@ static const char* detectByRegistry(FFCPUResult* cpu)
|
||||
cpu->coresOnline = cpu->coresPhysical = cpu->coresLogical = (uint16_t) cores;
|
||||
}
|
||||
|
||||
uint32_t mhz;
|
||||
if(ffRegReadUint(hKey, L"~MHz", &mhz, NULL))
|
||||
cpu->frequencyBase = mhz / 1000.0;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* detectCoreTypes(FFCPUResult* cpu)
|
||||
{
|
||||
FF_AUTO_FREE PROCESSOR_POWER_INFORMATION* pinfo = calloc(cpu->coresLogical, sizeof(PROCESSOR_POWER_INFORMATION));
|
||||
if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical)))
|
||||
return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed";
|
||||
|
||||
for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore)
|
||||
{
|
||||
uint32_t ifreq = 0;
|
||||
while (cpu->coreTypes[ifreq].freq != pinfo[icore].MhzLimit && cpu->coreTypes[ifreq].freq > 0)
|
||||
++ifreq;
|
||||
if (cpu->coreTypes[ifreq].freq == 0)
|
||||
cpu->coreTypes[ifreq].freq = pinfo[icore].MhzLimit;
|
||||
++cpu->coreTypes[ifreq].count;
|
||||
}
|
||||
|
||||
if (cpu->frequencyBase != cpu->frequencyBase)
|
||||
cpu->frequencyBase = pinfo->MaxMhz / 1000.0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -174,6 +193,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
detectSpeedByCpuid(cpu);
|
||||
if (options->showPeCoreCount) detectCoreTypes(cpu);
|
||||
|
||||
if (cpu->frequencyMax != cpu->frequencyMax)
|
||||
detectMaxSpeedBySmbios(cpu);
|
||||
|
||||
|
||||
@@ -66,6 +66,10 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk)
|
||||
#include <sys/attr.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
#define MNT_REMOVABLE 0x00000200
|
||||
#endif
|
||||
|
||||
struct CmnAttrBuf {
|
||||
uint32_t length;
|
||||
attrreference_t nameRef;
|
||||
@@ -132,13 +136,15 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks)
|
||||
ffStrbufInitS(&disk->filesystem, fs->f_fstypename);
|
||||
ffStrbufInit(&disk->name);
|
||||
disk->type = 0;
|
||||
disk->createTime = 0;
|
||||
|
||||
detectFsInfo(fs, disk);
|
||||
|
||||
if(fs->f_flags & MNT_RDONLY)
|
||||
disk->type |= FF_DISK_VOLUME_TYPE_READONLY_BIT;
|
||||
|
||||
struct stat st;
|
||||
if(stat(fs->f_mntonname, &st) == 0)
|
||||
if(stat(fs->f_mntonname, &st) == 0 && st.st_birthtimespec.tv_sec > 0)
|
||||
disk->createTime = (uint64_t)((st.st_birthtimespec.tv_sec * 1000) + (st.st_birthtimespec.tv_nsec / 1000000));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
#include <CoreVideo/CVDisplayLink.h>
|
||||
|
||||
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
#import <IOKit/graphics/IOGraphicsLib.h>
|
||||
extern CFDictionaryRef CoreDisplay_IODisplayCreateInfoDictionary(io_service_t framebuffer, IOOptionBits options) __attribute__((weak_import));
|
||||
#endif
|
||||
|
||||
static void detectDisplays(FFDisplayServerResult* ds)
|
||||
{
|
||||
@@ -38,6 +42,7 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
if(CoreDisplay_DisplayCreateInfoDictionary)
|
||||
{
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary(screen);
|
||||
@@ -48,6 +53,19 @@ static void detectDisplays(FFDisplayServerResult* ds)
|
||||
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if(CoreDisplay_IODisplayCreateInfoDictionary)
|
||||
{
|
||||
io_service_t servicePort = CGDisplayIOServicePort(screen);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
|
||||
if(displayInfo)
|
||||
{
|
||||
CFDictionaryRef productNames;
|
||||
if(!ffCfDictGetDict(displayInfo, CFSTR(kDisplayProductName), &productNames))
|
||||
ffCfDictGetString(productNames, CFSTR("en_US"), &name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ffdsAppendDisplay(ds,
|
||||
(uint32_t)CGDisplayModeGetPixelWidth(mode),
|
||||
|
||||
@@ -25,7 +25,11 @@ const char* ffDetectFontImpl(FFFontResult* result)
|
||||
{
|
||||
ffStrbufAppendS(&result->fonts[0], [NSFont systemFontOfSize:12].familyName.UTF8String);
|
||||
ffStrbufAppendS(&result->fonts[1], [NSFont userFontOfSize:12].familyName.UTF8String);
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
ffStrbufAppendS(&result->fonts[2], [NSFont monospacedSystemFontOfSize:12 weight:400].familyName.UTF8String);
|
||||
#else
|
||||
ffStrbufAppendS(&result->fonts[2], "");
|
||||
#endif
|
||||
ffStrbufAppendS(&result->fonts[3], [NSFont userFixedPitchFontOfSize:12].familyName.UTF8String);
|
||||
generateString(result);
|
||||
|
||||
|
||||
+26
-24
@@ -46,9 +46,9 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
{
|
||||
FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus);
|
||||
gpu->type = FF_GPU_TYPE_UNKNOWN;
|
||||
ffStrbufInitMove(&gpu->vendor, &result.vendor);
|
||||
ffStrbufInit(&gpu->vendor);
|
||||
ffStrbufInitMove(&gpu->name, &result.renderer);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInitMove(&gpu->driver, &result.vendor);
|
||||
ffStrbufInitF(&gpu->platformApi, "OpenGL %s", result.version.chars);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_UNSET;
|
||||
@@ -56,22 +56,18 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
gpu->dedicated = gpu->shared = (FFGPUMemory){0, 0};
|
||||
gpu->deviceId = 0;
|
||||
|
||||
if (ffStrbufIgnCaseEqualS(&gpu->vendor, "Mesa"))
|
||||
ffStrbufClear(&gpu->vendor);
|
||||
|
||||
if (!gpu->vendor.length)
|
||||
if (ffStrbufContainS(&gpu->name, "Apple"))
|
||||
{
|
||||
if (ffStrbufContainS(&gpu->name, "Apple"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
else if (ffStrbufContainS(&gpu->name, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
}
|
||||
if (ffStrbufEqualS(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
}
|
||||
else if (ffStrbufContainS(&gpu->name, "Intel"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_INTEL);
|
||||
else if (ffStrbufContainS(&gpu->name, "AMD") || ffStrbufContainS(&gpu->name, "ATI"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_AMD);
|
||||
else if (ffStrbufContainS(&gpu->name, "NVIDIA"))
|
||||
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_NVIDIA);
|
||||
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&result.version);
|
||||
@@ -83,20 +79,26 @@ const char* detectByOpenGL(FFlist* gpus)
|
||||
|
||||
const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result)
|
||||
{
|
||||
if (!options->forceVulkan)
|
||||
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_PCI)
|
||||
{
|
||||
const char* error = ffDetectGPUImpl(options, result);
|
||||
if (!error && result->length > 0) return NULL;
|
||||
}
|
||||
FFVulkanResult* vulkan = ffDetectVulkan();
|
||||
if (!vulkan->error && vulkan->gpus.length > 0)
|
||||
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_VULKAN)
|
||||
{
|
||||
ffListDestroy(result);
|
||||
ffListInitMove(result, &vulkan->gpus);
|
||||
return NULL;
|
||||
FFVulkanResult* vulkan = ffDetectVulkan();
|
||||
if (!vulkan->error && vulkan->gpus.length > 0)
|
||||
{
|
||||
ffListDestroy(result);
|
||||
ffListInitMove(result, &vulkan->gpus);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (options->detectionMethod <= FF_GPU_DETECTION_METHOD_OPENGL)
|
||||
{
|
||||
if (detectByOpenGL(result) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (detectByOpenGL(result) == NULL)
|
||||
return NULL;
|
||||
|
||||
return "GPU detection failed";
|
||||
}
|
||||
|
||||
@@ -5,10 +5,14 @@
|
||||
#ifndef MAC_OS_VERSION_13_0
|
||||
#define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001)
|
||||
#endif
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
#define MTLFeatureSet_macOS_GPUFamily1_v4 ((MTLFeatureSet) 10004)
|
||||
#define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005)
|
||||
#endif
|
||||
|
||||
const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
{
|
||||
if (@available(macOS 10.15, *))
|
||||
if (@available(macOS 10.13, *))
|
||||
{
|
||||
for (id<MTLDevice> device in MTLCopyAllDevices())
|
||||
{
|
||||
@@ -23,6 +27,12 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
}
|
||||
if (!gpu) continue;
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 2");
|
||||
else if ([device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Feature Set 1");
|
||||
#else // MAC_OS_X_VERSION_10_15
|
||||
if ([device supportsFamily:MTLGPUFamilyMetal3])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal 3");
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon3])
|
||||
@@ -32,15 +42,16 @@ const char* ffGpuDetectMetal(FFlist* gpus)
|
||||
else if ([device supportsFamily:MTLGPUFamilyCommon1])
|
||||
ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1");
|
||||
|
||||
if (device.hasUnifiedMemory)
|
||||
gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
|
||||
#endif
|
||||
|
||||
if (gpu->type == FF_GPU_TYPE_INTEGRATED)
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_INTEGRATED;
|
||||
gpu->shared.total = device.recommendedMaxWorkingSetSize;
|
||||
gpu->shared.used = device.currentAllocatedSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpu->type = FF_GPU_TYPE_DISCRETE;
|
||||
gpu->dedicated.total = device.recommendedMaxWorkingSetSize;
|
||||
gpu->dedicated.used = device.currentAllocatedSize;
|
||||
}
|
||||
|
||||
+143
-46
@@ -15,8 +15,68 @@
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
#if __has_include(<drm/drm.h>)
|
||||
#include <drm/drm.h>
|
||||
#define FF_HAVE_DRM_H 1
|
||||
#elif __has_include(<libdrm/drm.h>)
|
||||
#include <libdrm/drm.h>
|
||||
#define FF_HAVE_DRM_H 1
|
||||
#endif
|
||||
|
||||
#if FF_HAVE_DRM_H
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#if __aarch64__ && __has_include(<drm/asahi_drm.h>)
|
||||
#include <drm/asahi_drm.h>
|
||||
#define FF_HAVE_ASAHI_DRM_H 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if FF_HAVE_DRM_H
|
||||
static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
|
||||
{
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
||||
if (fd < 0) return "open(/dev/dri/drm_key) failed";
|
||||
|
||||
ffStrbufEnsureFixedLengthFree(&gpu->driver, 128);
|
||||
drm_version_t version = {
|
||||
.name = gpu->driver.chars,
|
||||
.name_len = gpu->driver.allocated,
|
||||
};
|
||||
if (ioctl(fd, DRM_IOCTL_VERSION, &version) < 0) return "ioctl(DRM_IOCTL_VERSION) failed";
|
||||
gpu->driver.length = (uint32_t) version.name_len;
|
||||
gpu->driver.chars[gpu->driver.length] = '\0';
|
||||
|
||||
if (version.version_major || version.version_minor || version.version_patchlevel)
|
||||
ffStrbufAppendF(&gpu->driver, " %d.%d.%d", version.version_major, version.version_minor, version.version_patchlevel);
|
||||
else
|
||||
{
|
||||
ffStrbufAppendS(pciDir, "/driver/module/version");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
{
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppend(&gpu->driver, buffer);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
|
||||
{
|
||||
#if FF_HAVE_DRM_H
|
||||
if (drmKey)
|
||||
{
|
||||
drmDetectDriver(gpu, pciDir, buffer, drmKey);
|
||||
if (gpu->driver.length > 0) return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
ffStrbufAppendS(pciDir, "/driver");
|
||||
char pathBuf[PATH_MAX];
|
||||
ssize_t resultLength = readlink(pciDir->chars, pathBuf, sizeof(pathBuf));
|
||||
@@ -35,8 +95,11 @@ static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer
|
||||
ffStrbufTrimRightSpace(buffer);
|
||||
ffStrbufAppendC(&gpu->driver, ' ');
|
||||
ffStrbufAppend(&gpu->driver, buffer);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
@@ -100,24 +163,26 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
|
||||
|
||||
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer)
|
||||
{
|
||||
if (!ffStrbufEndsWithS(pciDir, "/device")) // Must be in `/sys/class/drm/cardN/device`
|
||||
return;
|
||||
|
||||
// Works for Intel GPUs
|
||||
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
|
||||
ffStrbufSetNS(buffer, pciDir->length - (uint32_t) strlen("device"), pciDir->chars);
|
||||
ffStrbufAppendS(buffer, "gt_max_freq_mhz");
|
||||
char str[16];
|
||||
ssize_t len = ffReadFileData(buffer->chars, sizeof(str) - 1, str);
|
||||
if (len > 1)
|
||||
{
|
||||
str[len] = '\0';
|
||||
gpu->frequency = (double) strtoul(str, NULL, 10) / 1000.0;
|
||||
}
|
||||
|
||||
if (ffStrbufStartsWithS(&gpu->name, "Intel "))
|
||||
ffStrbufSubstrAfter(&gpu->name, (uint32_t) strlen("Intel "));
|
||||
gpu->type = ffStrbufStartsWithIgnCaseS(&gpu->name, "Arc ") ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED;
|
||||
|
||||
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");
|
||||
if (ffReadFileBuffer(pciDir->chars, buffer))
|
||||
gpu->frequency = ffStrbufToDouble(buffer) / 1000.0;
|
||||
}
|
||||
|
||||
static bool loadPciIds(FFstrbuf* pciids)
|
||||
@@ -143,9 +208,9 @@ static bool loadPciIds(FFstrbuf* pciids)
|
||||
return false;
|
||||
}
|
||||
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir)
|
||||
static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey)
|
||||
{
|
||||
const uint32_t drmDirPathLength = drmDir->length;
|
||||
const uint32_t drmDirPathLength = deviceDir->length;
|
||||
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)
|
||||
@@ -155,15 +220,23 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
return "Not a GPU device";
|
||||
|
||||
char pciPath[PATH_MAX];
|
||||
ssize_t pathLength = readlink(drmDir->chars, pciPath, sizeof(pciPath) - 1);
|
||||
if (pathLength <= 0)
|
||||
return "Unable to get PCI device path";
|
||||
pciPath[pathLength] = '\0';
|
||||
const char* pPciPath = strrchr(pciPath, '/');
|
||||
if (pPciPath)
|
||||
pPciPath++;
|
||||
const char* pPciPath = NULL;
|
||||
if (drmKey)
|
||||
{
|
||||
ssize_t pathLength = readlink(deviceDir->chars, pciPath, sizeof(pciPath) - 1);
|
||||
if (pathLength <= 0)
|
||||
return "Unable to get PCI device path";
|
||||
pciPath[pathLength] = '\0';
|
||||
pPciPath = strrchr(pciPath, '/');
|
||||
if (__builtin_expect(pPciPath != NULL, true))
|
||||
pPciPath++;
|
||||
else
|
||||
pPciPath = pciPath;
|
||||
}
|
||||
else
|
||||
pPciPath = pciPath;
|
||||
{
|
||||
pPciPath = memrchr(deviceDir->chars, '/', deviceDir->length) + 1;
|
||||
}
|
||||
|
||||
uint32_t pciDomain, pciBus, pciDevice, pciFunc;
|
||||
if (sscanf(pPciPath, "%" SCNx32 ":%" SCNx32 ":%" SCNx32 ".%" SCNx32, &pciDomain, &pciBus, &pciDevice, &pciFunc) != 4)
|
||||
@@ -181,10 +254,12 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc;
|
||||
gpu->frequency = FF_GPU_FREQUENCY_UNSET;
|
||||
|
||||
if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey);
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
ffStrbufAppendS(drmDir, "/revision");
|
||||
if (ffReadFileBuffer(drmDir->chars, buffer))
|
||||
ffStrbufAppendS(deviceDir, "/revision");
|
||||
if (ffReadFileBuffer(deviceDir->chars, buffer))
|
||||
{
|
||||
char* pend;
|
||||
uint64_t revision = strtoul(buffer->chars, &pend, 16);
|
||||
@@ -199,7 +274,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
#endif
|
||||
}
|
||||
}
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
|
||||
if (gpu->name.length == 0)
|
||||
@@ -213,18 +288,18 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu);
|
||||
}
|
||||
|
||||
pciDetectDriver(gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
pciDetectDriver(gpu, deviceDir, buffer, drmKey);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
|
||||
if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD)
|
||||
{
|
||||
pciDetectAmdSpecific(options, gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
pciDetectAmdSpecific(options, gpu, deviceDir, buffer);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
|
||||
{
|
||||
pciDetectIntelSpecific(gpu, drmDir, buffer);
|
||||
ffStrbufSubstrBefore(drmDir, drmDirPathLength);
|
||||
pciDetectIntelSpecific(gpu, deviceDir, buffer);
|
||||
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
|
||||
}
|
||||
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA)
|
||||
{
|
||||
@@ -261,7 +336,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir)
|
||||
FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey)
|
||||
{
|
||||
uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t");
|
||||
if (index == buffer->length) return "display-subsystem?";
|
||||
@@ -272,14 +347,34 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F
|
||||
ffStrbufInitStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId));
|
||||
ffStrbufInitStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
|
||||
ffStrbufInit(&gpu->driver);
|
||||
ffStrbufInit(&gpu->platformApi);
|
||||
ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey);
|
||||
gpu->temperature = FF_GPU_TEMP_UNSET;
|
||||
gpu->coreCount = FF_GPU_CORE_COUNT_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);
|
||||
pciDetectDriver(gpu, drmDir, buffer, drmKey);
|
||||
|
||||
#if FF_HAVE_ASAHI_DRM_H
|
||||
ffStrbufSetS(buffer, "/dev/dri/");
|
||||
ffStrbufAppendS(buffer, drmKey);
|
||||
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
|
||||
if (fd >= 0)
|
||||
{
|
||||
struct drm_asahi_params_global paramsGlobal = {};
|
||||
if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params){
|
||||
.param_group = DRM_ASAHI_GET_PARAMS,
|
||||
.pointer = (uint64_t) ¶msGlobal,
|
||||
.size = sizeof(paramsGlobal),
|
||||
}) >= 0)
|
||||
{
|
||||
gpu->coreCount = (int) paramsGlobal.num_cores_total_active;
|
||||
gpu->frequency = paramsGlobal.max_frequency_khz / 1e6;
|
||||
gpu->deviceId = paramsGlobal.chip_id;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -311,10 +406,10 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
ffStrbufSubstrBefore(&drmDir, drmDir.length - (uint32_t) strlen("/modalias"));
|
||||
|
||||
if (ffStrbufStartsWithS(&buffer, "pci:"))
|
||||
detectPci(options, gpus, &buffer, &drmDir);
|
||||
detectPci(options, gpus, &buffer, &drmDir, entry->d_name);
|
||||
#ifdef __aarch64__
|
||||
else if (ffStrbufStartsWithS(&buffer, "of:"))
|
||||
detectAsahi(gpus, &buffer, &drmDir);
|
||||
detectAsahi(gpus, &buffer, &drmDir, entry->d_name);
|
||||
#endif
|
||||
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
@@ -356,7 +451,7 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
ffStrbufSubstrBefore(&pciDir, pciDevDirLength);
|
||||
assert(ffStrbufStartsWithS(&buffer, "pci:"));
|
||||
|
||||
detectPci(options, gpus, &buffer, &pciDir);
|
||||
detectPci(options, gpus, &buffer, &pciDir, NULL);
|
||||
ffStrbufSubstrBefore(&pciDir, pciBaseDirLength);
|
||||
}
|
||||
|
||||
@@ -365,14 +460,16 @@ static const char* pciDetectGPUs(const FFGPUOptions* options, FFlist* gpus)
|
||||
|
||||
const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
||||
if (ffGPUDetectByDirectX(options, gpus) == NULL)
|
||||
if (options->detectionMethod == FF_GPU_DETECTION_METHOD_AUTO)
|
||||
{
|
||||
#ifdef FF_HAVE_DIRECTX_HEADERS
|
||||
const char* ffGPUDetectByDirectX(const FFGPUOptions* options, FFlist* gpus);
|
||||
if (ffGPUDetectByDirectX(options, gpus) == NULL)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
if (drmDetectGPUs(options, gpus) == NULL && gpus->length > 0)
|
||||
return NULL;
|
||||
|
||||
}
|
||||
return pciDetectGPUs(options, gpus);
|
||||
}
|
||||
|
||||
@@ -9,11 +9,22 @@
|
||||
|
||||
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import));
|
||||
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
#import <IOKit/graphics/IOGraphicsLib.h>
|
||||
extern CFDictionaryRef CoreDisplay_IODisplayCreateInfoDictionary(io_service_t framebuffer, IOOptionBits options) __attribute__((weak_import));
|
||||
#endif
|
||||
|
||||
static bool detectHdrSupportWithNSScreen(FFDisplayResult* display)
|
||||
{
|
||||
NSScreen* mainScreen = NSScreen.mainScreen;
|
||||
if (display->primary)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
return mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
|
||||
#else
|
||||
return mainScreen.maximumExtendedDynamicRangeColorComponentValue > 1;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
for (NSScreen* screen in NSScreen.screens)
|
||||
@@ -22,7 +33,11 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display)
|
||||
NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"];
|
||||
if (screenNumber && screenNumber.longValue == (long) display->id)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
return screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1;
|
||||
#else
|
||||
return screen.maximumExtendedDynamicRangeColorComponentValue > 1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,13 +46,19 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display)
|
||||
|
||||
const char* ffDetectMonitor(FFlist* results)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
if(!CoreDisplay_DisplayCreateInfoDictionary) return "CoreDisplay_DisplayCreateInfoDictionary is not available";
|
||||
|
||||
#endif
|
||||
const FFDisplayServerResult* displayServer = ffConnectDisplayServer();
|
||||
|
||||
FF_LIST_FOR_EACH(FFDisplayResult, display, displayServer->displays)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_DisplayCreateInfoDictionary((CGDirectDisplayID) display->id);
|
||||
#else
|
||||
io_service_t servicePort = CGDisplayIOServicePort((CGDirectDisplayID) display->id);
|
||||
CFDictionaryRef FF_CFTYPE_AUTO_RELEASE displayInfo = CoreDisplay_IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
|
||||
#endif
|
||||
if(!displayInfo) continue;
|
||||
|
||||
bool isVirtual = false;
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include "detection/opencl/opencl.h"
|
||||
|
||||
#if defined(FF_HAVE_OPENCL) || defined(__APPLE__)
|
||||
#ifdef __APPLE__
|
||||
#include <AvailabilityMacros.h>
|
||||
#if (MAC_OS_X_VERSION_MIN_REQUIRED > 1050) && !defined(__ppc__)
|
||||
#define MACOS_HAS_OPENCL
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(FF_HAVE_OPENCL) || defined(MACOS_HAS_OPENCL)
|
||||
|
||||
#include "common/library.h"
|
||||
#include "common/parsing.h"
|
||||
@@ -64,7 +71,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // defined(FF_HAVE_OPENCL) || defined(__APPLE__)
|
||||
#endif // defined(FF_HAVE_OPENCL) || defined(MACOS_HAS_OPENCL)
|
||||
|
||||
const char* ffDetectOpenCL(FFOpenCLResult* result)
|
||||
{
|
||||
@@ -84,7 +91,7 @@ const char* ffDetectOpenCL(FFOpenCLResult* result)
|
||||
|
||||
return openCLHandleData(&data, result);
|
||||
|
||||
#elif defined(__APPLE__) // FF_HAVE_OPENCL
|
||||
#elif defined(MACOS_HAS_OPENCL) // FF_HAVE_OPENCL
|
||||
|
||||
OpenCLData data;
|
||||
data.ffclGetPlatformIDs = clGetPlatformIDs;
|
||||
|
||||
@@ -97,8 +97,7 @@ void ffDetectOSImpl(FFOSResult* os)
|
||||
{
|
||||
parseSystemVersion(os);
|
||||
|
||||
if(ffStrbufStartsWithIgnCaseS(&os->name, "MacOS"))
|
||||
ffStrbufSetStatic(&os->id, "macos");
|
||||
ffStrbufSetStatic(&os->id, "macos");
|
||||
|
||||
if(os->version.length == 0)
|
||||
ffSysctlGetString("kern.osproductversion", &os->version);
|
||||
|
||||
@@ -31,7 +31,7 @@ static bool parseLsbRelease(const char* fileName, FFOSResult* result)
|
||||
|
||||
static bool parseOsRelease(const char* fileName, FFOSResult* result)
|
||||
{
|
||||
return ffParsePropFileValues(fileName, 10, (FFpropquery[]) {
|
||||
return ffParsePropFileValues(fileName, 11, (FFpropquery[]) {
|
||||
{"PRETTY_NAME =", &result->prettyName},
|
||||
{"NAME =", &result->name},
|
||||
{"ID =", &result->id},
|
||||
@@ -41,7 +41,8 @@ static bool parseOsRelease(const char* fileName, FFOSResult* result)
|
||||
{"VERSION =", &result->version},
|
||||
{"VERSION_ID =", &result->versionID},
|
||||
{"VERSION_CODENAME =", &result->codename},
|
||||
{"BUILD_ID =", &result->buildID}
|
||||
{"CODENAME =", &result->codename},
|
||||
{"BUILD_ID =", &result->buildID},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -156,6 +157,12 @@ static bool detectDebianDerived(FFOSResult* result)
|
||||
ffStrbufSetNS(&result->versionID, versionEnd - versionStart, result->prettyName.chars + versionStart);
|
||||
return true;
|
||||
}
|
||||
else if (ffStrbufStartsWithS(&result->name, "Loc-OS"))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "locos");
|
||||
ffStrbufSetS(&result->idLike, "debian");
|
||||
return true;
|
||||
}
|
||||
else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE))
|
||||
{
|
||||
ffStrbufSetS(&result->id, "pve");
|
||||
|
||||
@@ -14,6 +14,8 @@ typedef struct FFPackagesResult
|
||||
uint32_t eopkg;
|
||||
uint32_t flatpakSystem;
|
||||
uint32_t flatpakUser;
|
||||
uint32_t lpkg;
|
||||
uint32_t lpkgbuild;
|
||||
uint32_t nixDefault;
|
||||
uint32_t nixSystem;
|
||||
uint32_t nixUser;
|
||||
|
||||
@@ -412,6 +412,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
{
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_DPKG_BIT)) packageCounts->dpkg += getNumStrings(baseDir, "/var/lib/dpkg/status", "Status: install ok installed");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_LPKG_BIT)) packageCounts->lpkg += getNumStrings(baseDir, "/opt/Loc-OS-LPKG/installed-lpkg/Listinstalled-lpkg.list", "\n");
|
||||
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 += getFlatpak(baseDir, "/var/lib/flatpak");
|
||||
@@ -421,6 +422,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts,
|
||||
packageCounts->nixSystem += getNixPackages(baseDir, "/run/current-system");
|
||||
}
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PACMAN_BIT)) packageCounts->pacman += getNumElements(baseDir, "/var/lib/pacman/local", DT_DIR);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_LPKGBUILD_BIT)) packageCounts->lpkgbuild += getNumElements(baseDir, "/opt/Loc-OS-LPKG/lpkgbuild/remove", DT_REG);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_PKGTOOL_BIT)) packageCounts->pkgtool += getNumElements(baseDir, "/var/log/packages", DT_REG);
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_RPM_BIT)) packageCounts->rpm += getSQLite3Int(baseDir, "/var/lib/rpm/rpmdb.sqlite", "SELECT count(*) FROM Packages");
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_SNAP_BIT)) packageCounts->snap += getSnap(baseDir);
|
||||
@@ -508,30 +510,28 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
|
||||
ffStrbufAppendS(&profilePath, ".nix-profile");
|
||||
if (ffPathExists(profilePath.chars, FF_PATHTYPE_DIRECTORY))
|
||||
{
|
||||
result->nixUser = getNixPackages(&baseDir, ".nix-profile");
|
||||
result->nixUser += getNixPackages(&baseDir, ".nix-profile");
|
||||
}
|
||||
|
||||
// check if $XDG_STATE_HOME/nix/profile exists
|
||||
FF_STRBUF_AUTO_DESTROY stateDir = ffStrbufCreate();
|
||||
const char* stateHome = getenv("XDG_STATE_HOME");
|
||||
if(ffStrSet(stateHome))
|
||||
{
|
||||
ffStrbufSetS(&stateDir, stateHome);
|
||||
ffStrbufEnsureEndsWithC(&stateDir, '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY stateDir = ffStrbufCreate();
|
||||
const char* stateHome = getenv("XDG_STATE_HOME");
|
||||
if(ffStrSet(stateHome))
|
||||
{
|
||||
ffStrbufSetS(&stateDir, stateHome);
|
||||
ffStrbufEnsureEndsWithC(&stateDir, '/');
|
||||
}
|
||||
else
|
||||
{
|
||||
ffStrbufSet(&stateDir, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&stateDir, ".local/state/");
|
||||
}
|
||||
|
||||
ffStrbufSet(&profilePath, &stateDir);
|
||||
ffStrbufAppendS(&profilePath, "nix/profile");
|
||||
result->nixUser = getNixPackages(&stateDir, "nix/profile");
|
||||
ffStrbufSet(&stateDir, &instance.state.platform.homeDir);
|
||||
ffStrbufAppendS(&stateDir, ".local/state/");
|
||||
}
|
||||
|
||||
ffStrbufSet(&profilePath, &stateDir);
|
||||
ffStrbufAppendS(&profilePath, "nix/profile");
|
||||
result->nixUser += getNixPackages(&stateDir, "nix/profile");
|
||||
}
|
||||
|
||||
|
||||
if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT))
|
||||
result->flatpakUser = getFlatpak(&baseDir, "/.local/share/flatpak");
|
||||
}
|
||||
|
||||
@@ -7,17 +7,22 @@
|
||||
#include <IOKit/storage/IOBlockStorageDriver.h>
|
||||
#include <IOKit/storage/IOStorageDeviceCharacteristics.h>
|
||||
#include <IOKit/storage/IOStorageProtocolCharacteristics.h>
|
||||
#include <IOKit/storage/nvme/NVMeSMARTLibExternal.h>
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
#include <IOKit/storage/nvme/NVMeSMARTLibExternal.h>
|
||||
#endif
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
static inline void wrapIoDestroyPlugInInterface(IOCFPlugInInterface*** pluginInf)
|
||||
{
|
||||
assert(pluginInf);
|
||||
if (*pluginInf)
|
||||
IODestroyPlugInInterface(*pluginInf);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const char* detectSsdTemp(io_service_t entryPhysical, double* temp)
|
||||
{
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
__attribute__((__cleanup__(wrapIoDestroyPlugInInterface))) IOCFPlugInInterface** pluginInf = NULL;
|
||||
int32_t score;
|
||||
if (IOCreatePlugInInterfaceForService(entryPhysical, kIONVMeSMARTUserClientTypeID, kIOCFPlugInInterfaceID, &pluginInf, &score) != kIOReturnSuccess)
|
||||
@@ -36,6 +41,9 @@ static const char* detectSsdTemp(io_service_t entryPhysical, double* temp)
|
||||
|
||||
(*pluginInf)->Release(smartInf);
|
||||
return error;
|
||||
#else
|
||||
return "No support for old MacOS version";
|
||||
#endif
|
||||
}
|
||||
|
||||
const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
@@ -117,12 +125,14 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MAC_OS_X_VERSION_10_15
|
||||
if (options->temp)
|
||||
{
|
||||
FF_CFTYPE_AUTO_RELEASE CFBooleanRef nvmeSMARTCapable = IORegistryEntryCreateCFProperty(entryPhysical, CFSTR(kIOPropertyNVMeSMARTCapableKey), kCFAllocatorDefault, kNilOptions);
|
||||
if (nvmeSMARTCapable && CFBooleanGetValue(nvmeSMARTCapable))
|
||||
detectSsdTemp(entryPhysical, &device->temperature);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,10 @@ static void getProcessInformation(pid_t pid, FFstrbuf* processName, FFstrbuf* ex
|
||||
int mibs[] = { CTL_KERN, KERN_PROCARGS2, pid };
|
||||
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), NULL, &len, NULL, 0) == 0)
|
||||
{
|
||||
#ifndef MAC_OS_X_VERSION_10_15
|
||||
//don't know why if don't let len longer, proArgs2 and len will change during the following sysctl() in old MacOS version.
|
||||
len++;
|
||||
#endif
|
||||
FF_AUTO_FREE char* const procArgs2 = malloc(len);
|
||||
if (sysctl(mibs, sizeof(mibs) / sizeof(*mibs), procArgs2, &len, NULL, 0) == 0)
|
||||
{
|
||||
@@ -244,6 +248,8 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid)
|
||||
ffStrEquals(name, "guake-wrapped") ||
|
||||
ffStrEquals(name, "time") ||
|
||||
ffStrEquals(name, "hyfetch") || //when hyfetch uses fastfetch as backend
|
||||
ffStrEquals(name, "clifm") || //https://github.com/leo-arch/clifm/issues/289
|
||||
ffStrEquals(name, "valgrind") ||
|
||||
ffStrContainsIgnCase(name, "debug") ||
|
||||
ffStrContainsIgnCase(name, "not-found") ||
|
||||
ffStrEndsWith(name, ".sh")
|
||||
@@ -294,6 +300,7 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid)
|
||||
ffStrEquals(name, "xonsh") || // works in Linux but not in macOS because kernel returns `Python` in this case
|
||||
ffStrEquals(name, "login") ||
|
||||
ffStrEquals(name, "sshd") ||
|
||||
ffStrEquals(name, "clifm") || // https://github.com/leo-arch/clifm/issues/289
|
||||
ffStrEquals(name, "chezmoi") || // #762
|
||||
#ifdef __linux__
|
||||
ffStrStartsWith(name, "flatpak-") || // #707
|
||||
|
||||
@@ -135,13 +135,13 @@ const char* ffDetectWifi(FFlist* result)
|
||||
case kCWSecurityEnterprise:
|
||||
ffStrbufSetStatic(&item->conn.security, "Enterprise");
|
||||
break;
|
||||
case kCWSecurityWPA3Personal:
|
||||
case 11 /*kCWSecurityWPA3Personal*/:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA3 Personal");
|
||||
break;
|
||||
case kCWSecurityWPA3Enterprise:
|
||||
case 12 /*kCWSecurityWPA3Enterprise*/:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA3 Enterprise");
|
||||
break;
|
||||
case kCWSecurityWPA3Transition:
|
||||
case 13 /*kCWSecurityWPA3Transition*/:
|
||||
ffStrbufSetStatic(&item->conn.security, "WPA3 Transition");
|
||||
break;
|
||||
case 14 /*kCWSecurityOWE*/:
|
||||
|
||||
@@ -36,9 +36,17 @@ const char* ffDetectWifi(FFlist* result)
|
||||
item->conn.txRate = 0.0/0.0;
|
||||
|
||||
ffParsePropLines(ifconfig.chars, "ssid ", &item->conn.ssid);
|
||||
if (item->conn.ssid.length) ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' ');
|
||||
if (item->conn.ssid.length)
|
||||
{
|
||||
uint32_t ibssid = ffStrbufFirstIndexS(&item->conn.ssid, " bssid ");
|
||||
if (ibssid < item->conn.ssid.length)
|
||||
{
|
||||
ibssid += (uint32_t) strlen(" bssid ");
|
||||
ffStrbufSetS(&item->conn.macAddress, item->conn.ssid.chars + ibssid);
|
||||
}
|
||||
|
||||
ffParsePropLines(ifconfig.chars, "ether ", &item->conn.macAddress);
|
||||
ffStrbufSubstrBeforeFirstC(&item->conn.ssid, ' ');
|
||||
}
|
||||
|
||||
ffParsePropLines(ifconfig.chars, "media: ", &item->conn.protocol);
|
||||
if (item->conn.protocol.length)
|
||||
@@ -53,7 +61,7 @@ const char* ffDetectWifi(FFlist* result)
|
||||
}
|
||||
}
|
||||
|
||||
ffParsePropLines(ifconfig.chars, "status: ", &item->conn.macAddress);
|
||||
ffParsePropLines(ifconfig.chars, "status: ", &item->conn.status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,10 +234,13 @@ static bool printSpecificCommandHelp(const char* command)
|
||||
}
|
||||
}
|
||||
|
||||
yyjson_doc_free(doc);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
yyjson_doc_free(doc);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
.$2xOOko $1.$2odd,
|
||||
oX$1WW$2KOOOO. 'ON$1WW$20kkk.
|
||||
$1.$2k0XKOOOOOOcOON$1W$2NOOOOO.
|
||||
xOOOOOOOOOkkOOOOOOOOO;
|
||||
$1.$2O0OkkocxO000000kcdk0OO0OOkx
|
||||
k$1W$1M$2Xkkkkloxkkkx; :dxxxxddc...
|
||||
'kO0OOOOOkc .cl:..kk0KK0Okc
|
||||
;kOOO0000xd. dO00000Oo .xkO$1NMM$2XOOOO
|
||||
.dddxkOOOkddc.kKN$1WW$2N000000l.ddk0000OOOO.
|
||||
'dd:;ddddd;.dK$1MMMW$2K00KKK0O::ddxkO00Oko
|
||||
.okxkOKK0kkOO00KKOxxlodddddddl
|
||||
.00OOkkkkkkkkOOO00OOOO0O; .dddl
|
||||
'kkkkkxxkkkkkkkOOkxdxkxxddd.
|
||||
cddddddddxxkkkkkxddddddddddo
|
||||
'ddddddodddddddddddddddddddc
|
||||
$1.$2ddddddodddddddddodddddddc
|
||||
.odddo.
|
||||
|
||||
$1.$2kOOkkk;
|
||||
lkK$1WN$2kkkxc
|
||||
kkxkkkkkkx.
|
||||
,,..xxx.
|
||||
@@ -0,0 +1,18 @@
|
||||
$3..;:::::::;.
|
||||
.0X'$1''''''''''''$3'N:
|
||||
:Xd$1,.'''''''''''''''$3lKx
|
||||
.0o$1'.'''''''''''''''''''$3:K;
|
||||
.O$1;.'$3okOx:$1'''''''''$3,dOOx:$1''$3O;
|
||||
xc$1.'$3xXl$1 $3kX;$1''$2:cc;$1''$3kXl$1 $3OX;$1''$3k.
|
||||
'x$1..'$3:0X0Xx$1',$2OOOOOd$1,:$30X0Xx$1'''$3o:
|
||||
::$1..'$2,clollxOOOOOOOOdlddlc$1''''$3d
|
||||
l'$1..$2':kkkkOOOOOOOOOOOOkkkx,$1'''$3x
|
||||
o$1...''''',$2codxkkxxxdl$1:''''''''$3d.
|
||||
d$1...''''''''''''''''''''''''''$3o.
|
||||
d$1..''''$3,loc,$1''''''''$3;os:,$1'''''$3d'
|
||||
:d$1..'$3,dKXXXXX0kxxxk0XXXXXX0l$1'''$3,O.
|
||||
'0$1..'$3cKXXXXXXXXXXXXXXXXXXXXXXk$1'''$3ck
|
||||
'0$1'.'$3cXXXXXXXXXXXXXXXXXXXXXXXXXO$1'''$3od
|
||||
.0$1,.''$30XXXXXXXXXXXXXXXXXXXXXXXXXXo$1'''$3k;
|
||||
cc$1..''$3XXXXXXXXXXXXXXXXXXXXXXXXXXXk$1''''$3k
|
||||
l$1...',$3XXXXXXXXXXXXXXXXXXXXXXXXXXXO$1''''$3d.
|
||||
@@ -0,0 +1,5 @@
|
||||
@..@
|
||||
(----)
|
||||
( >__< )
|
||||
^^ ~~ ^^
|
||||
| Spoink! |
|
||||
+35
-19
@@ -1558,18 +1558,6 @@ static const FFlogo F[] = {
|
||||
.colorKeys = FF_COLOR_FG_BLUE,
|
||||
.colorTitle = FF_COLOR_FG_BLUE,
|
||||
},
|
||||
// FedoraOnyx placeholder - Currently does not have a logo
|
||||
//{
|
||||
//.names = {"Fedora_onyx", "fedora-onyx", "fedora-linux-onyx", "fedora-linux_onyx"},
|
||||
//.type = FF_LOGO_LINE_TYPE_ALTER_BIT,
|
||||
//.lines = FASTFETCH_DATATEXT_LOGO_FEDORA_ONYX,
|
||||
//.colors = {
|
||||
//FF_COLOR_FG_BLUE,
|
||||
//FF_COLOR_FG_WHITE,
|
||||
//},
|
||||
//.colorKeys = FF_COLOR_FG_BLUE,
|
||||
//.colorTitle = FF_COLOR_FG_BLUE,
|
||||
//},
|
||||
// FedoraCoreOS
|
||||
{
|
||||
.names = {"Fedora_coreos", "fedora-coreos", "fedora-linux-coreos", "fedora-linux_coreos"},
|
||||
@@ -1678,6 +1666,17 @@ static const FFlogo F[] = {
|
||||
.colorKeys = FF_COLOR_FG_MAGENTA,
|
||||
.colorTitle = FF_COLOR_FG_WHITE,
|
||||
},
|
||||
// Furreto
|
||||
{
|
||||
.names = {"Furreto"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_FURRETO,
|
||||
.colors = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
FF_COLOR_FG_LIGHT_MAGENTA,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_CYAN,
|
||||
.colorTitle = FF_COLOR_FG_CYAN,
|
||||
},
|
||||
// LAST
|
||||
{},
|
||||
};
|
||||
@@ -2121,13 +2120,11 @@ static const FFlogo K[] = {
|
||||
},
|
||||
// KDENeon
|
||||
{
|
||||
.names = {"KDE", "kde-neon"},
|
||||
.names = {"KDE", "kde-neon", "kde neon"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_KDE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_GREEN,
|
||||
.colorTitle = FF_COLOR_FG_GREEN,
|
||||
},
|
||||
// Kibojoe
|
||||
{
|
||||
@@ -2385,6 +2382,18 @@ static const FFlogo L[] = {
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
},
|
||||
// Loc-OS
|
||||
{
|
||||
.names = {"loc-os", "Loc-OS Linux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_LOCOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_BLACK,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_WHITE,
|
||||
},
|
||||
.colorKeys = FF_COLOR_FG_YELLOW,
|
||||
.colorTitle = FF_COLOR_FG_RED,
|
||||
},
|
||||
// Lunar
|
||||
{
|
||||
.names = {"Lunar"},
|
||||
@@ -2542,7 +2551,7 @@ static const FFlogo M[] = {
|
||||
},
|
||||
// Manjaro
|
||||
{
|
||||
.names = {"manjaro", "manjaro-linux"},
|
||||
.names = {"manjaro", "manjaro-linux", "manjarolinux"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_MANJARO,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
@@ -3821,6 +3830,14 @@ static const FFlogo S[] = {
|
||||
FF_COLOR_FG_YELLOW,
|
||||
},
|
||||
},
|
||||
// SpoinkOS
|
||||
{
|
||||
.names = {"SpoinkOS", "spoink-os"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_SPOINKOS,
|
||||
.colors = {
|
||||
FF_COLOR_FG_GREEN,
|
||||
},
|
||||
},
|
||||
// Slackel
|
||||
{
|
||||
.names = {"Slackel"},
|
||||
@@ -4044,10 +4061,9 @@ static const FFlogo T[] = {
|
||||
.names = {"TorizonCore"},
|
||||
.lines = FASTFETCH_DATATEXT_LOGO_TORIZONCORE,
|
||||
.colors = {
|
||||
FF_COLOR_FG_LIGHT_WHITE,
|
||||
FF_COLOR_FG_YELLOW,
|
||||
FF_COLOR_FG_BLUE,
|
||||
FF_COLOR_FG_LIGHT_BLACK,
|
||||
FF_COLOR_FG_MAGENTA,
|
||||
FF_COLOR_FG_BLUE
|
||||
},
|
||||
},
|
||||
// Trisquel
|
||||
|
||||
@@ -128,12 +128,6 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (bios.version.length == 0)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", "bios_version is not set.");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "date", &bios.date);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "release", &bios.release);
|
||||
@@ -165,7 +159,7 @@ void ffInitBiosOptions(FFBiosOptions* options)
|
||||
ffOptionInitModuleBaseInfo(
|
||||
&options->moduleInfo,
|
||||
FF_BIOS_MODULE_NAME,
|
||||
"Print BIOS name, version, release date, etc",
|
||||
"Print information of 1st-stage bootloader (name, version, release date, etc)",
|
||||
ffParseBiosCommandOptions,
|
||||
ffParseBiosJsonObject,
|
||||
ffPrintBios,
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
#include "common/printing.h"
|
||||
#include "common/jsonconfig.h"
|
||||
#include "detection/bootmgr/bootmgr.h"
|
||||
#include "modules/bootmgr/bootmgr.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_BOOTMGR_NUM_FORMAT_ARGS 4
|
||||
|
||||
void ffPrintBootmgr(FFBootmgrOptions* options)
|
||||
{
|
||||
FFBootmgrResult bootmgr = {
|
||||
.name = ffStrbufCreate(),
|
||||
.firmware = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
const char* error = ffDetectBootmgr(&bootmgr);
|
||||
|
||||
if(error)
|
||||
{
|
||||
ffPrintError(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error);
|
||||
return;
|
||||
}
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY firmwareName = ffStrbufCreateCopy(&bootmgr.firmware);
|
||||
#ifndef __APPLE__
|
||||
ffStrbufSubstrAfterLastC(&firmwareName, '\\');
|
||||
#else
|
||||
ffStrbufSubstrAfterLastC(&firmwareName, '/');
|
||||
#endif
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
ffStrbufWriteTo(&bootmgr.name, stdout);
|
||||
if (firmwareName.length > 0)
|
||||
printf(" - %s\n", firmwareName.chars);
|
||||
else
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_PRINT_FORMAT_CHECKED(FF_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_BOOTMGR_NUM_FORMAT_ARGS, ((FFformatarg[]) {
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bootmgr.name},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &bootmgr.firmware},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &firmwareName},
|
||||
{FF_FORMAT_ARG_TYPE_BOOL, &bootmgr.secureBoot},
|
||||
}));
|
||||
}
|
||||
|
||||
ffStrbufDestroy(&bootmgr.name);
|
||||
ffStrbufDestroy(&bootmgr.firmware);
|
||||
}
|
||||
|
||||
bool ffParseBootmgrCommandOptions(FFBootmgrOptions* options, const char* key, const char* value)
|
||||
{
|
||||
const char* subKey = ffOptionTestPrefix(key, FF_BOOTMGR_MODULE_NAME);
|
||||
if (!subKey) return false;
|
||||
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ffParseBootmgrJsonObject(FFBootmgrOptions* 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_BOOTMGR_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
|
||||
void ffGenerateBootmgrJsonConfig(FFBootmgrOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
__attribute__((__cleanup__(ffDestroyBootmgrOptions))) FFBootmgrOptions defaultOptions;
|
||||
ffInitBootmgrOptions(&defaultOptions);
|
||||
|
||||
ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs);
|
||||
}
|
||||
|
||||
void ffGenerateBootmgrJsonResult(FF_MAYBE_UNUSED FFBootmgrOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
FFBootmgrResult bootmgr = {
|
||||
.name = ffStrbufCreate(),
|
||||
.firmware = ffStrbufCreate(),
|
||||
};
|
||||
|
||||
const char* error = ffDetectBootmgr(&bootmgr);
|
||||
|
||||
if (error)
|
||||
{
|
||||
yyjson_mut_obj_add_str(doc, module, "error", error);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result");
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "name", &bootmgr.name);
|
||||
yyjson_mut_obj_add_strbuf(doc, obj, "firmware", &bootmgr.firmware);
|
||||
yyjson_mut_obj_add_bool(doc, obj, "secureBoot", bootmgr.secureBoot);
|
||||
|
||||
exit:
|
||||
ffStrbufDestroy(&bootmgr.name);
|
||||
ffStrbufDestroy(&bootmgr.firmware);
|
||||
}
|
||||
|
||||
void ffPrintBootmgrHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_BOOTMGR_MODULE_NAME, "{4} ({2})", FF_BOOTMGR_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Name / description",
|
||||
"Firmware file path",
|
||||
"Firmware file name",
|
||||
"Is secure boot enabled",
|
||||
}));
|
||||
}
|
||||
|
||||
void ffInitBootmgrOptions(FFBootmgrOptions* options)
|
||||
{
|
||||
ffOptionInitModuleBaseInfo(
|
||||
&options->moduleInfo,
|
||||
FF_BOOTMGR_MODULE_NAME,
|
||||
"Print information of 2nd-stage bootloader (name, firmware, etc)",
|
||||
ffParseBootmgrCommandOptions,
|
||||
ffParseBootmgrJsonObject,
|
||||
ffPrintBootmgr,
|
||||
ffGenerateBootmgrJsonResult,
|
||||
ffPrintBootmgrHelpFormat,
|
||||
ffGenerateBootmgrJsonConfig
|
||||
);
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
}
|
||||
|
||||
void ffDestroyBootmgrOptions(FFBootmgrOptions* options)
|
||||
{
|
||||
ffOptionDestroyModuleArg(&options->moduleArgs);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_BOOTMGR_MODULE_NAME "Bootmgr"
|
||||
|
||||
void ffPrintBootmgr(FFBootmgrOptions* options);
|
||||
void ffInitBootmgrOptions(FFBootmgrOptions* options);
|
||||
void ffDestroyBootmgrOptions(FFBootmgrOptions* options);
|
||||
@@ -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 FFBootmgrOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
} FFBootmgrOptions;
|
||||
+95
-23
@@ -6,16 +6,24 @@
|
||||
#include "modules/cpu/cpu.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_CPU_NUM_FORMAT_ARGS 8
|
||||
#define FF_CPU_NUM_FORMAT_ARGS 10
|
||||
|
||||
static int sortCores(const FFCPUCore* a, const FFCPUCore* b)
|
||||
{
|
||||
return (int)b->freq - (int)a->freq;
|
||||
}
|
||||
|
||||
void ffPrintCPU(FFCPUOptions* options)
|
||||
{
|
||||
FFCPUResult cpu;
|
||||
cpu.temperature = FF_CPU_TEMP_UNSET;
|
||||
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
|
||||
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
|
||||
ffStrbufInit(&cpu.name);
|
||||
ffStrbufInit(&cpu.vendor);
|
||||
FFCPUResult cpu = {
|
||||
.temperature = FF_CPU_TEMP_UNSET,
|
||||
.frequencyMin = 0.0/0.0,
|
||||
.frequencyMax = 0.0/0.0,
|
||||
.frequencyBase = 0.0/0.0,
|
||||
.frequencyBiosLimit = 0.0/0.0,
|
||||
.name = ffStrbufCreate(),
|
||||
.vendor = ffStrbufCreate()
|
||||
};
|
||||
|
||||
const char* error = ffDetectCPU(options, &cpu);
|
||||
|
||||
@@ -29,6 +37,20 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate();
|
||||
if (options->showPeCoreCount)
|
||||
{
|
||||
uint32_t typeCount = 0;
|
||||
while (cpu.coreTypes[typeCount].count != 0 && typeCount < sizeof(cpu.coreTypes) / sizeof(cpu.coreTypes[0])) typeCount++;
|
||||
if (typeCount > 0)
|
||||
{
|
||||
qsort(cpu.coreTypes, typeCount, sizeof(cpu.coreTypes[0]), (void*) sortCores);
|
||||
|
||||
for (uint32_t i = 0; i < typeCount; i++)
|
||||
ffStrbufAppendF(&coreTypes, "%s%u", i == 0 ? "" : "+", cpu.coreTypes[i].count);
|
||||
}
|
||||
}
|
||||
|
||||
if(options->moduleArgs.outputFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT);
|
||||
@@ -45,13 +67,17 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
else
|
||||
ffStrbufAppendS(&str, "Unknown");
|
||||
|
||||
if(cpu.coresOnline > 1)
|
||||
if(coreTypes.length > 0)
|
||||
ffStrbufAppendF(&str, " (%s)", coreTypes.chars);
|
||||
else if(cpu.coresOnline > 1)
|
||||
ffStrbufAppendF(&str, " (%u)", cpu.coresOnline);
|
||||
|
||||
double freq = cpu.frequencyMax;
|
||||
if(freq != freq)
|
||||
double freq = cpu.frequencyBiosLimit;
|
||||
if(!(freq > 0.0000001))
|
||||
freq = cpu.frequencyMax;
|
||||
if(!(freq > 0.0000001))
|
||||
freq = cpu.frequencyBase;
|
||||
if(freq == freq)
|
||||
if(freq > 0.0000001)
|
||||
ffStrbufAppendF(&str, " @ %.*f GHz", options->freqNdigits, freq);
|
||||
|
||||
if(cpu.temperature == cpu.temperature) //FF_CPU_TEMP_UNSET
|
||||
@@ -64,6 +90,20 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
}
|
||||
else
|
||||
{
|
||||
char freqBase[32], freqMax[32], freqBioslimit[32];
|
||||
if (cpu.frequencyBase > 0)
|
||||
snprintf(freqBase, sizeof(freqBase), "%.*f", options->freqNdigits, cpu.frequencyBase);
|
||||
else
|
||||
freqBase[0] = 0;
|
||||
if (cpu.frequencyMax > 0)
|
||||
snprintf(freqMax, sizeof(freqMax), "%.*f", options->freqNdigits, cpu.frequencyMax);
|
||||
else
|
||||
freqMax[0] = 0;
|
||||
if (cpu.frequencyBiosLimit > 0)
|
||||
snprintf(freqBioslimit, sizeof(freqBioslimit), "%.*f", options->freqNdigits, cpu.frequencyBiosLimit);
|
||||
else
|
||||
freqBioslimit[0] = 0;
|
||||
|
||||
FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate();
|
||||
ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs);
|
||||
FF_PRINT_FORMAT_CHECKED(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_CPU_NUM_FORMAT_ARGS, ((FFformatarg[]){
|
||||
@@ -72,9 +112,11 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresPhysical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresLogical},
|
||||
{FF_FORMAT_ARG_TYPE_UINT16, &cpu.coresOnline},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyBase},
|
||||
{FF_FORMAT_ARG_TYPE_DOUBLE, &cpu.frequencyMax},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}
|
||||
{FF_FORMAT_ARG_TYPE_STRING, freqBase},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, freqMax},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &tempStr},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes},
|
||||
{FF_FORMAT_ARG_TYPE_STRING, freqBioslimit},
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -83,7 +125,7 @@ void ffPrintCPU(FFCPUOptions* options)
|
||||
ffStrbufDestroy(&cpu.vendor);
|
||||
}
|
||||
|
||||
bool ffParseCPUCPUOptions(FFCPUOptions* options, const char* key, const char* value)
|
||||
bool ffParseCPUCommandOptions(FFCPUOptions* options, const char* key, const char* value)
|
||||
{
|
||||
const char* subKey = ffOptionTestPrefix(key, FF_CPU_MODULE_NAME);
|
||||
if (!subKey) return false;
|
||||
@@ -99,6 +141,12 @@ bool ffParseCPUCPUOptions(FFCPUOptions* options, const char* key, const char* va
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subKey, "show-pe-core-count"))
|
||||
{
|
||||
options->showPeCoreCount = ffOptionParseBoolean(value);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -124,6 +172,12 @@ void ffParseCPUJsonObject(FFCPUOptions* options, yyjson_val* module)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "showPeCoreCount"))
|
||||
{
|
||||
options->showPeCoreCount = yyjson_get_bool(val);
|
||||
continue;
|
||||
}
|
||||
|
||||
ffPrintError(FF_CPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key);
|
||||
}
|
||||
}
|
||||
@@ -139,16 +193,22 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
|
||||
if (defaultOptions.freqNdigits != options->freqNdigits)
|
||||
yyjson_mut_obj_add_uint(doc, module, "freqNdigits", options->freqNdigits);
|
||||
|
||||
if (defaultOptions.showPeCoreCount != options->showPeCoreCount)
|
||||
yyjson_mut_obj_add_bool(doc, module, "showPeCoreCount", options->showPeCoreCount);
|
||||
}
|
||||
|
||||
void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module)
|
||||
{
|
||||
FFCPUResult cpu;
|
||||
cpu.temperature = FF_CPU_TEMP_UNSET;
|
||||
cpu.coresPhysical = cpu.coresLogical = cpu.coresOnline = 0;
|
||||
cpu.frequencyMin = cpu.frequencyMax = cpu.frequencyBase = 0.0/0.0;
|
||||
ffStrbufInit(&cpu.name);
|
||||
ffStrbufInit(&cpu.vendor);
|
||||
FFCPUResult cpu = {
|
||||
.temperature = FF_CPU_TEMP_UNSET,
|
||||
.frequencyMin = 0.0/0.0,
|
||||
.frequencyMax = 0.0/0.0,
|
||||
.frequencyBase = 0.0/0.0,
|
||||
.frequencyBiosLimit = 0.0/0.0,
|
||||
.name = ffStrbufCreate(),
|
||||
.vendor = ffStrbufCreate()
|
||||
};
|
||||
|
||||
const char* error = ffDetectCPU(options, &cpu);
|
||||
|
||||
@@ -175,6 +235,15 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
yyjson_mut_obj_add_real(doc, frequency, "base", cpu.frequencyBase);
|
||||
yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax);
|
||||
yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin);
|
||||
yyjson_mut_obj_add_real(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++)
|
||||
{
|
||||
yyjson_mut_val* core = yyjson_mut_arr_add_obj(doc, coreTypes);
|
||||
yyjson_mut_obj_add_uint(doc, core, "count", cpu.coreTypes[i].count);
|
||||
yyjson_mut_obj_add_uint(doc, core, "freq", cpu.coreTypes[i].freq);
|
||||
}
|
||||
|
||||
yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature);
|
||||
}
|
||||
@@ -193,7 +262,9 @@ void ffPrintCPUHelpFormat(void)
|
||||
"Online core count",
|
||||
"Base frequency",
|
||||
"Max frequency",
|
||||
"Temperature (formatted)"
|
||||
"Temperature (formatted)",
|
||||
"Logical core count grouped by frequency",
|
||||
"Bios limited frequency",
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -203,7 +274,7 @@ void ffInitCPUOptions(FFCPUOptions* options)
|
||||
&options->moduleInfo,
|
||||
FF_CPU_MODULE_NAME,
|
||||
"Print CPU name, frequency, etc",
|
||||
ffParseCPUCPUOptions,
|
||||
ffParseCPUCommandOptions,
|
||||
ffParseCPUJsonObject,
|
||||
ffPrintCPU,
|
||||
ffGenerateCPUJsonResult,
|
||||
@@ -214,6 +285,7 @@ void ffInitCPUOptions(FFCPUOptions* options)
|
||||
options->temp = false;
|
||||
options->tempConfig = (FFColorRangeConfig) { 60, 80 };
|
||||
options->freqNdigits = 2;
|
||||
options->showPeCoreCount = false;
|
||||
}
|
||||
|
||||
void ffDestroyCPUOptions(FFCPUOptions* options)
|
||||
|
||||
@@ -12,4 +12,5 @@ typedef struct FFCPUOptions
|
||||
bool temp;
|
||||
FFColorRangeConfig tempConfig;
|
||||
uint8_t freqNdigits;
|
||||
bool showPeCoreCount;
|
||||
} FFCPUOptions;
|
||||
|
||||
+42
-7
@@ -127,6 +127,7 @@ void ffPrintGPU(FFGPUOptions* options)
|
||||
ffStrbufDestroy(&gpu->vendor);
|
||||
ffStrbufDestroy(&gpu->name);
|
||||
ffStrbufDestroy(&gpu->driver);
|
||||
ffStrbufDestroy(&gpu->platformApi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,9 +144,15 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(subKey, "force-vulkan"))
|
||||
if (ffStrEqualsIgnCase(subKey, "detection-method"))
|
||||
{
|
||||
options->forceVulkan = ffOptionParseBoolean(value);
|
||||
options->detectionMethod = (FFGPUDetectionMethod) ffOptionParseEnum(key, value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_GPU_DETECTION_METHOD_AUTO },
|
||||
{ "pci", FF_GPU_DETECTION_METHOD_PCI },
|
||||
{ "vulkan", FF_GPU_DETECTION_METHOD_VULKAN },
|
||||
{ "opengl", FF_GPU_DETECTION_METHOD_OPENGL },
|
||||
{},
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -190,9 +197,20 @@ void ffParseGPUJsonObject(FFGPUOptions* options, yyjson_val* module)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ffStrEqualsIgnCase(key, "forceVulkan"))
|
||||
if (ffStrEqualsIgnCase(key, "detectionMethod"))
|
||||
{
|
||||
options->forceVulkan = yyjson_get_bool(val);
|
||||
int value;
|
||||
const char* error = ffJsonConfigParseEnum(val, &value, (FFKeyValuePair[]) {
|
||||
{ "auto", FF_GPU_DETECTION_METHOD_AUTO },
|
||||
{ "pci", FF_GPU_DETECTION_METHOD_PCI },
|
||||
{ "vulkan", FF_GPU_DETECTION_METHOD_VULKAN },
|
||||
{ "opengl", FF_GPU_DETECTION_METHOD_OPENGL },
|
||||
{},
|
||||
});
|
||||
if (error)
|
||||
ffPrintError(FF_GPU_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Invalid %s value: %s", key, error);
|
||||
else
|
||||
options->detectionMethod = (FFGPUDetectionMethod) value;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -229,8 +247,24 @@ void ffGenerateGPUJsonConfig(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
if (options->driverSpecific != defaultOptions.driverSpecific)
|
||||
yyjson_mut_obj_add_bool(doc, module, "driverSpecific", options->driverSpecific);
|
||||
|
||||
if (options->forceVulkan != defaultOptions.forceVulkan)
|
||||
yyjson_mut_obj_add_bool(doc, module, "forceVulkan", options->forceVulkan);
|
||||
if (options->detectionMethod != defaultOptions.detectionMethod)
|
||||
{
|
||||
switch (options->detectionMethod)
|
||||
{
|
||||
case FF_GPU_DETECTION_METHOD_AUTO:
|
||||
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "auto");
|
||||
break;
|
||||
case FF_GPU_DETECTION_METHOD_PCI:
|
||||
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "pci");
|
||||
break;
|
||||
case FF_GPU_DETECTION_METHOD_VULKAN:
|
||||
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "vulkan");
|
||||
break;
|
||||
case FF_GPU_DETECTION_METHOD_OPENGL:
|
||||
yyjson_mut_obj_add_str(doc, module, "detectionMethod", "opengl");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ffTempsGenerateJsonConfig(doc, module, defaultOptions.temp, defaultOptions.tempConfig, options->temp, options->tempConfig);
|
||||
|
||||
@@ -327,6 +361,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_
|
||||
ffStrbufDestroy(&gpu->vendor);
|
||||
ffStrbufDestroy(&gpu->name);
|
||||
ffStrbufDestroy(&gpu->driver);
|
||||
ffStrbufDestroy(&gpu->platformApi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +399,7 @@ void ffInitGPUOptions(FFGPUOptions* options)
|
||||
ffOptionInitModuleArg(&options->moduleArgs);
|
||||
|
||||
options->driverSpecific = false;
|
||||
options->forceVulkan = false;
|
||||
options->detectionMethod = FF_GPU_DETECTION_METHOD_AUTO;
|
||||
options->temp = false;
|
||||
options->hideType = FF_GPU_TYPE_UNKNOWN;
|
||||
options->tempConfig = (FFColorRangeConfig) { 60, 80 };
|
||||
|
||||
@@ -12,15 +12,24 @@ typedef enum FFGPUType
|
||||
FF_GPU_TYPE_DISCRETE,
|
||||
} FFGPUType;
|
||||
|
||||
typedef enum FFGPUDetectionMethod
|
||||
{
|
||||
FF_GPU_DETECTION_METHOD_AUTO,
|
||||
FF_GPU_DETECTION_METHOD_PCI,
|
||||
FF_GPU_DETECTION_METHOD_VULKAN,
|
||||
FF_GPU_DETECTION_METHOD_OPENGL,
|
||||
} FFGPUDetectionMethod;
|
||||
|
||||
typedef struct FFGPUOptions
|
||||
{
|
||||
FFModuleBaseInfo moduleInfo;
|
||||
FFModuleArgs moduleArgs;
|
||||
|
||||
FFGPUType hideType;
|
||||
FFGPUDetectionMethod detectionMethod;
|
||||
bool temp;
|
||||
bool driverSpecific;
|
||||
bool forceVulkan;
|
||||
bool forceMethod;
|
||||
FFColorRangeConfig tempConfig;
|
||||
FFColorRangeConfig percent;
|
||||
} FFGPUOptions;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "modules/bluetooth/bluetooth.h"
|
||||
#include "modules/brightness/brightness.h"
|
||||
#include "modules/board/board.h"
|
||||
#include "modules/bootmgr/bootmgr.h"
|
||||
#include "modules/break/break.h"
|
||||
#include "modules/camera/camera.h"
|
||||
#include "modules/chassis/chassis.h"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "modules/bios/option.h"
|
||||
#include "modules/bluetooth/option.h"
|
||||
#include "modules/board/option.h"
|
||||
#include "modules/bootmgr/option.h"
|
||||
#include "modules/break/option.h"
|
||||
#include "modules/brightness/option.h"
|
||||
#include "modules/camera/option.h"
|
||||
|
||||
@@ -28,6 +28,8 @@ typedef enum FFPackagesFlags
|
||||
FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18,
|
||||
FF_PACKAGES_FLAG_AM_BIT = 1 << 19,
|
||||
FF_PACKAGES_FLAG_SORCERY_BIT = 1 << 20,
|
||||
FF_PACKAGES_FLAG_LPKG_BIT = 1 << 21,
|
||||
FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22,
|
||||
} FFPackagesFlags;
|
||||
|
||||
typedef struct FFPackagesOptions
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include "modules/packages/packages.h"
|
||||
#include "util/stringUtils.h"
|
||||
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 30
|
||||
#define FF_PACKAGES_NUM_FORMAT_ARGS 32
|
||||
|
||||
void ffPrintPackages(FFPackagesOptions* options)
|
||||
{
|
||||
@@ -66,6 +66,8 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
FF_PRINT_PACKAGE(opkg)
|
||||
FF_PRINT_PACKAGE(am)
|
||||
FF_PRINT_PACKAGE(sorcery)
|
||||
FF_PRINT_PACKAGE(lpkg)
|
||||
FF_PRINT_PACKAGE(lpkgbuild)
|
||||
|
||||
putchar('\n');
|
||||
}
|
||||
@@ -102,6 +104,8 @@ void ffPrintPackages(FFPackagesOptions* options)
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.opkg},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.am},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.sorcery},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.lpkg},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &counts.lpkgbuild},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &nixAll},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &flatpakAll},
|
||||
{FF_FORMAT_ARG_TYPE_UINT, &brewAll},
|
||||
@@ -153,6 +157,10 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key,
|
||||
case 'F': if (false);
|
||||
FF_TEST_PACKAGE_NAME(FLATPAK)
|
||||
break;
|
||||
case 'L': if (false);
|
||||
FF_TEST_PACKAGE_NAME(LPKG)
|
||||
FF_TEST_PACKAGE_NAME(LPKGBUILD)
|
||||
break;
|
||||
case 'M': if (false);
|
||||
FF_TEST_PACKAGE_NAME(MACPORTS)
|
||||
break;
|
||||
@@ -254,6 +262,10 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module)
|
||||
case 'F': if (false);
|
||||
FF_TEST_PACKAGE_NAME(FLATPAK)
|
||||
break;
|
||||
case 'L': if (false);
|
||||
FF_TEST_PACKAGE_NAME(LPKG)
|
||||
FF_TEST_PACKAGE_NAME(LPKGBUILD)
|
||||
break;
|
||||
case 'M': if (false);
|
||||
FF_TEST_PACKAGE_NAME(MACPORTS)
|
||||
break;
|
||||
@@ -313,6 +325,8 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do
|
||||
FF_TEST_PACKAGE_NAME(EMERGE)
|
||||
FF_TEST_PACKAGE_NAME(EOPKG)
|
||||
FF_TEST_PACKAGE_NAME(FLATPAK)
|
||||
FF_TEST_PACKAGE_NAME(LPKG)
|
||||
FF_TEST_PACKAGE_NAME(LPKGBUILD)
|
||||
FF_TEST_PACKAGE_NAME(NIX)
|
||||
FF_TEST_PACKAGE_NAME(OPKG)
|
||||
FF_TEST_PACKAGE_NAME(PACMAN)
|
||||
@@ -379,7 +393,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy
|
||||
|
||||
void ffPrintPackagesHelpFormat(void)
|
||||
{
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_PACKAGES_MODULE_NAME, "{2} (pacman){?3}[{3}]{?}, {4} (dpkg), {5} (rpm), {6} (emerge), {7} (eopkg), {8} (xbps), {9} (nix-system), {10} (nix-user), {11} (nix-default), {12} (apk), {13} (pkg), {14} (flatpak-system), {15} (flatpack-user), {16} (snap), {17} (brew), {18} (brew-cask), {19} (MacPorts), {20} (scoop), {21} (choco), {22} (pkgtool), {23} (paludis), {24} (winget), {25} (opkg), {26} (am), {27} (sorcery), {28} (lpkg), {29} (lpkgbuild)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) {
|
||||
"Number of all packages",
|
||||
"Number of pacman packages",
|
||||
"Pacman branch on manjaro",
|
||||
@@ -407,6 +421,8 @@ void ffPrintPackagesHelpFormat(void)
|
||||
"Number of opkg packages",
|
||||
"Number of am packages",
|
||||
"Number of sorcery packages",
|
||||
"Number of lpkg packages",
|
||||
"Number of lpkgbuild packages",
|
||||
"Total number of all nix packages",
|
||||
"Total number of all flatpak packages",
|
||||
"Total number of all brew packages",
|
||||
|
||||
@@ -7,6 +7,7 @@ void ffOptionsInitModules(FFOptionsModules* options)
|
||||
ffInitBiosOptions(&options->bios);
|
||||
ffInitBluetoothOptions(&options->bluetooth);
|
||||
ffInitBoardOptions(&options->board);
|
||||
ffInitBootmgrOptions(&options->bootmgr);
|
||||
ffInitBreakOptions(&options->break_);
|
||||
ffInitBrightnessOptions(&options->brightness);
|
||||
ffInitCameraOptions(&options->camera);
|
||||
@@ -73,6 +74,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options)
|
||||
ffDestroyBiosOptions(&options->bios);
|
||||
ffDestroyBluetoothOptions(&options->bluetooth);
|
||||
ffDestroyBoardOptions(&options->board);
|
||||
ffDestroyBootmgrOptions(&options->bootmgr);
|
||||
ffDestroyBreakOptions(&options->break_);
|
||||
ffDestroyBrightnessOptions(&options->brightness);
|
||||
ffDestroyCameraOptions(&options->camera);
|
||||
|
||||
@@ -8,6 +8,7 @@ typedef struct FFOptionsModules
|
||||
FFBiosOptions bios;
|
||||
FFBluetoothOptions bluetooth;
|
||||
FFBoardOptions board;
|
||||
FFBootmgrOptions bootmgr;
|
||||
FFBreakOptions break_;
|
||||
FFBrightnessOptions brightness;
|
||||
FFCPUOptions cpu;
|
||||
|
||||
@@ -3,15 +3,11 @@
|
||||
#include "util/stringUtils.h"
|
||||
#include "util/windows/unicode.h"
|
||||
#include "util/windows/registry.h"
|
||||
#include "util/windows/nt.h"
|
||||
|
||||
#include <winternl.h>
|
||||
#include <Windows.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
NTSTATUS NTAPI RtlGetVersion(
|
||||
_Inout_ PRTL_OSVERSIONINFOW lpVersionInformation
|
||||
);
|
||||
|
||||
static void getExePath(FFPlatform* platform)
|
||||
{
|
||||
wchar_t exePathW[MAX_PATH];
|
||||
@@ -184,8 +180,13 @@ static void getSystemReleaseAndVersion(FFPlatform* platform)
|
||||
(unsigned) ubr);
|
||||
|
||||
ffStrbufInit(&platform->systemDisplayVersion);
|
||||
if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &platform->systemDisplayVersion, NULL) && osVersion.szCSDVersion[0])
|
||||
ffStrbufSetWS(&platform->systemDisplayVersion, osVersion.szCSDVersion);
|
||||
if(!ffRegReadStrbuf(hKey, L"DisplayVersion", &platform->systemDisplayVersion, NULL))
|
||||
{
|
||||
if (osVersion.szCSDVersion[0])
|
||||
ffStrbufSetWS(&platform->systemDisplayVersion, osVersion.szCSDVersion);
|
||||
else
|
||||
ffRegReadStrbuf(hKey, L"ReleaseId", &platform->systemDisplayVersion, NULL); // For old Windows 10
|
||||
}
|
||||
|
||||
ffRegReadStrbuf(hKey, L"BuildLabEx", &platform->systemVersion, NULL);
|
||||
|
||||
|
||||
+65
-21
@@ -79,6 +79,26 @@ bool ffGetSmbiosValue(const char* devicesPath, const char* classPath, FFstrbuf*
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef struct FFSmbios20EntryPoint
|
||||
{
|
||||
uint8_t AnchorString[4];
|
||||
uint8_t EntryPointStructureChecksum;
|
||||
uint8_t EntryPointLength;
|
||||
uint8_t SmbiosMajorVersion;
|
||||
uint8_t SmbiosMinorVersion;
|
||||
uint16_t MaximumStructureSize;
|
||||
uint8_t EntryPointRevision;
|
||||
uint8_t FormattedArea[5];
|
||||
uint8_t IntermediateAnchorString[5];
|
||||
uint8_t IntermediateChecksum;
|
||||
uint16_t StructureTableLength;
|
||||
uint32_t StructureTableAddress;
|
||||
uint16_t NumberOfSmbiosStructures;
|
||||
uint8_t SmbiosBcdRevision;
|
||||
} __attribute__((__packed__)) FFSmbios20EntryPoint;
|
||||
static_assert(offsetof(FFSmbios20EntryPoint, SmbiosBcdRevision) == 0x1E,
|
||||
"FFSmbios30EntryPoint: Wrong struct alignment");
|
||||
|
||||
typedef struct FFSmbios30EntryPoint
|
||||
{
|
||||
uint8_t AnchorString[5];
|
||||
@@ -94,7 +114,13 @@ typedef struct FFSmbios30EntryPoint
|
||||
} __attribute__((__packed__)) FFSmbios30EntryPoint;
|
||||
|
||||
static_assert(offsetof(FFSmbios30EntryPoint, StructureTableAddress) == 0x10,
|
||||
"FFSmbiosProcessorInfo: Wrong struct alignment");
|
||||
"FFSmbios30EntryPoint: Wrong struct alignment");
|
||||
|
||||
typedef union FFSmbiosEntryPoint
|
||||
{
|
||||
FFSmbios20EntryPoint Smbios20;
|
||||
FFSmbios30EntryPoint Smbios30;
|
||||
} FFSmbiosEntryPoint;
|
||||
|
||||
const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
{
|
||||
@@ -107,55 +133,73 @@ const FFSmbiosHeaderTable* ffGetSmbiosHeaderTable()
|
||||
if (!ffAppendFileBuffer("/sys/firmware/dmi/tables/DMI", &buffer))
|
||||
#endif
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY strEntry = ffStrbufCreate();
|
||||
// Only support SMBIOS 3.x for simplification
|
||||
FF_STRBUF_AUTO_DESTROY strEntryAddress = ffStrbufCreate();
|
||||
#ifdef __FreeBSD__
|
||||
if (!ffSettingsGetFreeBSDKenv("hint.smbios.0.mem", &strEntry))
|
||||
if (!ffSettingsGetFreeBSDKenv("hint.smbios.0.mem", &strEntryAddress))
|
||||
return NULL;
|
||||
#else
|
||||
if (!ffParsePropFile("/sys/firmware/efi/systab", "SMBIOS3=", &strEntry))
|
||||
return NULL;
|
||||
{
|
||||
FF_STRBUF_AUTO_DESTROY systab = ffStrbufCreate();
|
||||
if (!ffAppendFileBuffer("/sys/firmware/efi/systab", &systab))
|
||||
return NULL;
|
||||
if (!ffParsePropLines(systab.chars, "SMBIOS3=", &strEntryAddress) &&
|
||||
!ffParsePropLines(systab.chars, "SMBIOS=", &strEntryAddress))
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
loff_t pEntry = (loff_t) strtol(strEntry.chars, NULL, 0);
|
||||
if (pEntry == 0) return NULL;
|
||||
loff_t entryAddress = (loff_t) strtol(strEntryAddress.chars, NULL, 16);
|
||||
if (entryAddress == 0) return NULL;
|
||||
|
||||
FF_AUTO_CLOSE_FD int fd = open("/dev/mem", O_RDONLY);
|
||||
if (fd < 0) return NULL;
|
||||
|
||||
FFSmbios30EntryPoint entryPoint;
|
||||
if (pread(fd, &entryPoint, sizeof(entryPoint), pEntry) != sizeof(entryPoint))
|
||||
FFSmbiosEntryPoint entryPoint;
|
||||
if (pread(fd, &entryPoint, sizeof(entryPoint), entryAddress) < 0x10)
|
||||
{
|
||||
// `pread /dev/mem` returns EFAULT in FreeBSD
|
||||
// https://stackoverflow.com/questions/69372330/how-to-read-dev-mem-using-read
|
||||
void* p = mmap(NULL, sizeof(entryPoint), PROT_READ, MAP_SHARED, fd, pEntry);
|
||||
void* p = mmap(NULL, sizeof(entryPoint), PROT_READ, MAP_SHARED, fd, entryAddress);
|
||||
if (p == MAP_FAILED) return NULL;
|
||||
memcpy(&entryPoint, p, sizeof(entryPoint));
|
||||
munmap(p, sizeof(entryPoint));
|
||||
}
|
||||
|
||||
if (memcmp(entryPoint.AnchorString, "_SM3_", sizeof(entryPoint.AnchorString)) != 0 ||
|
||||
entryPoint.EntryPointLength != sizeof(entryPoint))
|
||||
return NULL;
|
||||
|
||||
ffStrbufEnsureFixedLengthFree(&buffer, entryPoint.StructureTableMaximumSize);
|
||||
if (pread(fd, buffer.chars, entryPoint.StructureTableMaximumSize, pEntry) == (loff_t) entryPoint.StructureTableMaximumSize)
|
||||
uint32_t tableLength = 0;
|
||||
loff_t tableAddress = 0;
|
||||
if (memcmp(entryPoint.Smbios20.AnchorString, "_SM_", sizeof(entryPoint.Smbios20.AnchorString)) == 0)
|
||||
{
|
||||
buffer.length = (uint32_t) entryPoint.StructureTableMaximumSize;
|
||||
if (entryPoint.Smbios20.EntryPointLength != sizeof(entryPoint.Smbios20))
|
||||
return NULL;
|
||||
tableLength = entryPoint.Smbios20.StructureTableLength;
|
||||
tableAddress = (loff_t) entryPoint.Smbios20.StructureTableAddress;
|
||||
}
|
||||
else if (memcmp(entryPoint.Smbios30.AnchorString, "_SM3_", sizeof(entryPoint.Smbios30.AnchorString)) == 0)
|
||||
{
|
||||
if (entryPoint.Smbios30.EntryPointLength != sizeof(entryPoint.Smbios30))
|
||||
return NULL;
|
||||
tableLength = entryPoint.Smbios30.StructureTableMaximumSize;
|
||||
tableAddress = (loff_t) entryPoint.Smbios30.StructureTableAddress;
|
||||
}
|
||||
|
||||
ffStrbufEnsureFixedLengthFree(&buffer, tableLength);
|
||||
if (pread(fd, buffer.chars, tableLength, tableAddress) == tableLength)
|
||||
{
|
||||
buffer.length = tableLength;
|
||||
buffer.chars[buffer.length] = '\0';
|
||||
}
|
||||
else
|
||||
{
|
||||
// entryPoint.StructureTableAddress must be page aligned.
|
||||
// Unaligned physical memory access results in all kinds of crashes.
|
||||
void* p = mmap(NULL, entryPoint.StructureTableMaximumSize, PROT_READ, MAP_SHARED, fd, (loff_t) entryPoint.StructureTableAddress);
|
||||
void* p = mmap(NULL, tableLength, PROT_READ, MAP_SHARED, fd, tableAddress);
|
||||
if (p == MAP_FAILED)
|
||||
{
|
||||
ffStrbufDestroy(&buffer); // free buffer and reset state
|
||||
return NULL;
|
||||
}
|
||||
ffStrbufSetNS(&buffer, entryPoint.StructureTableMaximumSize, (char*) p);
|
||||
munmap(p, entryPoint.StructureTableMaximumSize);
|
||||
ffStrbufSetNS(&buffer, tableLength, (char*) p);
|
||||
munmap(p, tableLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <winnt.h>
|
||||
#include <winternl.h>
|
||||
|
||||
typedef struct _PROCESSOR_POWER_INFORMATION {
|
||||
ULONG Number;
|
||||
ULONG MaxMhz;
|
||||
ULONG CurrentMhz;
|
||||
ULONG MhzLimit;
|
||||
ULONG MaxIdleState;
|
||||
ULONG CurrentIdleState;
|
||||
} PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
|
||||
|
||||
NTSTATUS NTAPI NtPowerInformation(
|
||||
IN POWER_INFORMATION_LEVEL InformationLevel,
|
||||
IN PVOID InputBuffer OPTIONAL,
|
||||
IN ULONG InputBufferLength,
|
||||
OUT PVOID OutputBuffer OPTIONAL,
|
||||
IN ULONG OutputBufferLength);
|
||||
|
||||
|
||||
NTSTATUS NTAPI RtlGetVersion(
|
||||
_Inout_ PRTL_OSVERSIONINFOW lpVersionInformation
|
||||
);
|
||||
Reference in New Issue
Block a user