Merge pull request #949 from fastfetch-cli/dev

Release: v2.13.0
This commit is contained in:
Carter Li
2024-05-20 13:28:45 +00:00
committed by GitHub
64 changed files with 1365 additions and 254 deletions
+2 -5
View File
@@ -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?
+1 -1
View File
@@ -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
+37
View File
@@ -1,3 +1,39 @@
# 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 +56,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
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.12.0
VERSION 2.13.0
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
+83 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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':
+21 -5
View File
@@ -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"
@@ -1445,10 +1455,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",
+1
View File
@@ -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,
+11 -6
View File
@@ -1197,13 +1197,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 -10
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -1,5 +1,6 @@
#include "bios.h"
#include "util/smbiosHelper.h"
#include "util/windows/registry.h"
#include <ntstatus.h>
#include <winternl.h>
+50
View File
@@ -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;
}
+12
View File
@@ -0,0 +1,12 @@
#pragma once
#include "fastfetch.h"
typedef struct FFBootmgrResult
{
FFstrbuf name;
FFstrbuf firmware;
bool secureBoot;
} FFBootmgrResult;
const char* ffDetectBootmgr(FFBootmgrResult* bios);
+12
View File
@@ -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;
}
+43
View File
@@ -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;
}
+27
View File
@@ -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";
}
+53
View File
@@ -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;
}
+24
View File
@@ -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"
+4 -1
View File
@@ -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
}
+9 -1
View File
@@ -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);
+23 -5
View File
@@ -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, &current, &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);
detectCoreCount(cpu);
cpu->temperature = options->temp ? detectCpuTemp(&cpu->name) : FF_CPU_TEMP_UNSET;
+56
View File
@@ -11,6 +11,62 @@ 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>");
}
}
uint32_t ifreq = (uint32_t) -1;
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;
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;
+49 -11
View File
@@ -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,10 +103,28 @@ 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 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)
@@ -119,38 +137,58 @@ 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;
}
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;
}
+25 -7
View File
@@ -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);
@@ -166,6 +160,27 @@ static const char* detectByRegistry(FFCPUResult* cpu)
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;
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
detectNCores(cpu);
@@ -174,6 +189,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (error)
return error;
detectSpeedByCpuid(cpu);
detectCoreTypes(cpu);
if (cpu->frequencyMax != cpu->frequencyMax)
detectMaxSpeedBySmbios(cpu);
+7 -1
View File
@@ -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),
+4
View File
@@ -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
View File
@@ -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";
}
+15 -4
View File
@@ -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
View File
@@ -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) &paramsGlobal,
.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);
}
+22 -1
View File
@@ -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;
+10 -3
View File
@@ -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;
+1 -2
View File
@@ -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);
+9 -2
View File
@@ -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");
+2
View File
@@ -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;
+18 -18
View File
@@ -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
+3 -3
View File
@@ -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*/:
+11 -3
View File
@@ -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);
}
}
+3
View File
@@ -234,10 +234,13 @@ static bool printSpecificCommandHelp(const char* command)
}
}
yyjson_doc_free(doc);
return true;
}
}
}
yyjson_doc_free(doc);
return false;
}
+22
View File
@@ -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.
+18
View File
@@ -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.
+5
View File
@@ -0,0 +1,5 @@
@..@
(----)
( >__< )
^^ ~~ ^^
| Spoink! |
+35 -19
View File
@@ -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
+1 -7
View File
@@ -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,
+143
View File
@@ -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);
}
+9
View File
@@ -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);
+11
View File
@@ -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;
+73 -20
View File
@@ -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);
@@ -48,10 +56,12 @@ void ffPrintCPU(FFCPUOptions* options)
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 +74,33 @@ void ffPrintCPU(FFCPUOptions* options)
}
else
{
FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate();
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);
}
else
ffStrbufAppendF(&coreTypes, "%u", cpu.coresOnline);
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 +109,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},
}));
}
}
@@ -143,12 +182,15 @@ void ffGenerateCPUJsonConfig(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_
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 +217,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 +244,9 @@ void ffPrintCPUHelpFormat(void)
"Online core count",
"Base frequency",
"Max frequency",
"Temperature (formatted)"
"Temperature (formatted)",
"Logical core count grouped by frequency",
"Bios limited frequency",
}));
}
+42 -7
View File
@@ -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 };
+10 -1
View File
@@ -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;
+1
View File
@@ -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"
+1
View File
@@ -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"
+2
View File
@@ -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
+18 -2
View File
@@ -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",
+2
View File
@@ -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);
+1
View File
@@ -8,6 +8,7 @@ typedef struct FFOptionsModules
FFBiosOptions bios;
FFBluetoothOptions bluetooth;
FFBoardOptions board;
FFBootmgrOptions bootmgr;
FFBreakOptions break_;
FFBrightnessOptions brightness;
FFCPUOptions cpu;
+8 -7
View File
@@ -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
View File
@@ -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);
}
}
+25
View File
@@ -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
);