From 85b4679373c2783b8884a55d69a4ab2cbd7b0780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 14 May 2024 22:03:28 +0800 Subject: [PATCH 01/65] Logo: fix Manjaro Linux Fix #921 --- src/logo/builtin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index be92989e6..2eb7e59ab 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -2542,7 +2542,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, From 8c7edf4d2dcc41084d9a0e4aacba31e1553beee9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 15 May 2024 16:26:29 +0800 Subject: [PATCH 02/65] Bios (Linux): detect boot manager & secure boot --- src/detection/bios/bios.h | 2 + src/detection/bios/bios_linux.c | 98 ++++++++++++++++++++++++++++++++- src/modules/bios/bios.c | 20 ++++--- 3 files changed, 112 insertions(+), 8 deletions(-) diff --git a/src/detection/bios/bios.h b/src/detection/bios/bios.h index 5272c5ca1..241024b9b 100644 --- a/src/detection/bios/bios.h +++ b/src/detection/bios/bios.h @@ -9,6 +9,8 @@ typedef struct FFBiosResult FFstrbuf vendor; FFstrbuf version; FFstrbuf type; + FFstrbuf bootmgr; + bool secureBoot; } FFBiosResult; const char* ffDetectBios(FFBiosResult* bios); diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index fa794d1c2..ecb009082 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -4,15 +4,111 @@ #include -const char* ffDetectBios(FFBiosResult* bios) +// 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; + +uint8_t ffEvBits(uint16_t val, uint8_t mask, uint8_t shift) +{ + return (uint8_t) ((val & (mask << shift)) >> shift); +} + +static void ffUcs2ToUtf8(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 | ffEvBits(chars[i], 0x1f, 6))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); + } + else + { + ffStrbufAppendC(result, (char) (0xe0 | ffEvBits(chars[i], 0xf, 12))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 6))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); + } + } +} + +#define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/" +#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" + +const char *detectBootmgr(FFstrbuf *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####"; + + FFEfiLoadOption *efiOption = (FFEfiLoadOption *)&buffer[4]; + uint32_t descLen = 0; + while (efiOption->Description[descLen]) ++descLen; + + 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 + ffUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, result); + return NULL; + } + } + + if (!result->length) ffUcs2ToUtf8(efiOption->Description, result); + + return NULL; +} + +const char *detectSecureBoot(bool* result) +{ + uint8_t buffer[5]; + if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6) + return "Failed to read efivar: SecureBoot"; + + *result = buffer[4] == 1; + return NULL; +} + +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); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version); if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE)) + { ffStrbufSetStatic(&bios->type, "UEFI"); + detectBootmgr(&bios->bootmgr); + } else ffStrbufSetStatic(&bios->type, "BIOS"); + detectSecureBoot(&bios->secureBoot); return NULL; } diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index b135b958b..9989b60cc 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -4,7 +4,7 @@ #include "modules/bios/bios.h" #include "util/stringUtils.h" -#define FF_BIOS_NUM_FORMAT_ARGS 5 +#define FF_BIOS_NUM_FORMAT_ARGS 7 void ffPrintBios(FFBiosOptions* options) { @@ -14,6 +14,8 @@ void ffPrintBios(FFBiosOptions* options) ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); ffStrbufInit(&bios.type); + ffStrbufInit(&bios.bootmgr); + bios.secureBoot = false; const char* error = ffDetectBios(&bios); @@ -65,6 +67,8 @@ void ffPrintBios(FFBiosOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &bios.vendor}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.version}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.type}, + {FF_FORMAT_ARG_TYPE_STRBUF, &bios.bootmgr}, + {FF_FORMAT_ARG_TYPE_BOOL, &bios.secureBoot}, })); } @@ -74,6 +78,7 @@ exit: ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); ffStrbufDestroy(&bios.type); + ffStrbufDestroy(&bios.bootmgr); } bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const char* value) @@ -119,6 +124,8 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); ffStrbufInit(&bios.type); + ffStrbufInit(&bios.bootmgr); + bios.secureBoot = false; const char* error = ffDetectBios(&bios); @@ -128,18 +135,14 @@ 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); yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &bios.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "version", &bios.version); yyjson_mut_obj_add_strbuf(doc, obj, "type", &bios.type); + yyjson_mut_obj_add_strbuf(doc, obj, "bootmgr", &bios.bootmgr); + yyjson_mut_obj_add_bool(doc, obj, "secureBoot", bios.secureBoot); exit: ffStrbufDestroy(&bios.date); @@ -147,6 +150,7 @@ exit: ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); ffStrbufDestroy(&bios.type); + ffStrbufDestroy(&bios.bootmgr); } void ffPrintBiosHelpFormat(void) @@ -157,6 +161,8 @@ void ffPrintBiosHelpFormat(void) "bios vendor", "bios version", "firmware type", + "Boot manager used to boot the system", + "Is secure boot enabled", })); } From 06a8f12d6adfc439f8e9e7f3a4872a7d70fe6887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 15 May 2024 20:39:22 +0800 Subject: [PATCH 03/65] Bios (Windows): detect secure boot state & boot manager Boot manager detection requires Administrator privilege to work --- src/detection/bios/bios_linux.c | 46 +----------------- src/detection/bios/bios_windows.c | 79 +++++++++++++++++++++++++++++++ src/detection/bios/efi.h | 47 ++++++++++++++++++ 3 files changed, 127 insertions(+), 45 deletions(-) create mode 100644 src/detection/bios/efi.h diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index ecb009082..08056d9a8 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -1,55 +1,11 @@ #include "bios.h" #include "common/io/io.h" #include "util/smbiosHelper.h" +#include "efi.h" #include -// 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; - -uint8_t ffEvBits(uint16_t val, uint8_t mask, uint8_t shift) -{ - return (uint8_t) ((val & (mask << shift)) >> shift); -} - -static void ffUcs2ToUtf8(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 | ffEvBits(chars[i], 0x1f, 6))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); - } - else - { - ffStrbufAppendC(result, (char) (0xe0 | ffEvBits(chars[i], 0xf, 12))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 6))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); - } - } -} - #define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/" -#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" const char *detectBootmgr(FFstrbuf *result) { diff --git a/src/detection/bios/bios_windows.c b/src/detection/bios/bios_windows.c index d8a305493..d1bbd4e4f 100644 --- a/src/detection/bios/bios_windows.c +++ b/src/detection/bios/bios_windows.c @@ -1,8 +1,11 @@ #include "bios.h" #include "util/smbiosHelper.h" +#include "util/windows/registry.h" +#include "efi.h" #include #include +#include typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION { @@ -51,6 +54,76 @@ typedef struct FFSmbiosBios static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18, "FFSmbiosBios: Wrong struct alignment"); +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 *detectBootmgr(FFstrbuf *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"; + + FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; + uint32_t descLen = 0; + while (efiOption->Description[descLen]) ++descLen; + + 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 + ffUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, result); + return NULL; + } + } + + if (!result->length) ffUcs2ToUtf8(efiOption->Description, result); + return NULL; +} + +const char *detectSecureBoot(bool* 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) + return "RegGetValueW(HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\SecureBoot\\State) failed"; + *result = !!uefiSecureBootEnabled; + return NULL; +} + const char* ffDetectBios(FFBiosResult* bios) { const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); @@ -84,6 +157,12 @@ const char* ffDetectBios(FFBiosResult* bios) case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break; default: break; } + + if (sbei.FirmwareType == FirmwareTypeUefi) + { + detectSecureBoot(&bios->secureBoot); + detectBootmgr(&bios->bootmgr); + } } return NULL; diff --git a/src/detection/bios/efi.h b/src/detection/bios/efi.h new file mode 100644 index 000000000..3878954bd --- /dev/null +++ b/src/detection/bios/efi.h @@ -0,0 +1,47 @@ +#include "fastfetch.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; + +uint8_t ffEvBits(uint16_t val, uint8_t mask, uint8_t shift) +{ + return (uint8_t) ((val & (mask << shift)) >> shift); +} + +static void ffUcs2ToUtf8(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 | ffEvBits(chars[i], 0x1f, 6))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); + } + else + { + ffStrbufAppendC(result, (char) (0xe0 | ffEvBits(chars[i], 0xf, 12))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 6))); + ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); + } + } +} + +#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" From 7c03fc155037d78b9ecc3e95442753aaaddf285c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 15 May 2024 21:09:26 +0800 Subject: [PATCH 04/65] Bios: move bootmgr detection to a new module --- src/detection/bios/bios.h | 2 - src/detection/bios/bios_linux.c | 52 --------------------- src/detection/bios/bios_windows.c | 78 ------------------------------- src/modules/bios/bios.c | 14 +----- 4 files changed, 1 insertion(+), 145 deletions(-) diff --git a/src/detection/bios/bios.h b/src/detection/bios/bios.h index 241024b9b..5272c5ca1 100644 --- a/src/detection/bios/bios.h +++ b/src/detection/bios/bios.h @@ -9,8 +9,6 @@ typedef struct FFBiosResult FFstrbuf vendor; FFstrbuf version; FFstrbuf type; - FFstrbuf bootmgr; - bool secureBoot; } FFBiosResult; const char* ffDetectBios(FFBiosResult* bios); diff --git a/src/detection/bios/bios_linux.c b/src/detection/bios/bios_linux.c index 08056d9a8..86342c159 100644 --- a/src/detection/bios/bios_linux.c +++ b/src/detection/bios/bios_linux.c @@ -1,57 +1,9 @@ #include "bios.h" #include "common/io/io.h" #include "util/smbiosHelper.h" -#include "efi.h" #include -#define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/" - -const char *detectBootmgr(FFstrbuf *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####"; - - FFEfiLoadOption *efiOption = (FFEfiLoadOption *)&buffer[4]; - uint32_t descLen = 0; - while (efiOption->Description[descLen]) ++descLen; - - 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 - ffUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, result); - return NULL; - } - } - - if (!result->length) ffUcs2ToUtf8(efiOption->Description, result); - - return NULL; -} - -const char *detectSecureBoot(bool* result) -{ - uint8_t buffer[5]; - if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) != 6) - return "Failed to read efivar: SecureBoot"; - - *result = buffer[4] == 1; - return NULL; -} - const char *ffDetectBios(FFBiosResult *bios) { ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_date", "/sys/class/dmi/id/bios_date", &bios->date); @@ -59,12 +11,8 @@ const char *ffDetectBios(FFBiosResult *bios) ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_vendor", "/sys/class/dmi/id/bios_vendor", &bios->vendor); ffGetSmbiosValue("/sys/devices/virtual/dmi/id/bios_version", "/sys/class/dmi/id/bios_version", &bios->version); if (ffPathExists("/sys/firmware/efi", FF_PATHTYPE_DIRECTORY) || ffPathExists("/sys/firmware/acpi/tables/UEFI", FF_PATHTYPE_FILE)) - { ffStrbufSetStatic(&bios->type, "UEFI"); - detectBootmgr(&bios->bootmgr); - } else ffStrbufSetStatic(&bios->type, "BIOS"); - detectSecureBoot(&bios->secureBoot); return NULL; } diff --git a/src/detection/bios/bios_windows.c b/src/detection/bios/bios_windows.c index d1bbd4e4f..d7a954074 100644 --- a/src/detection/bios/bios_windows.c +++ b/src/detection/bios/bios_windows.c @@ -1,11 +1,9 @@ #include "bios.h" #include "util/smbiosHelper.h" #include "util/windows/registry.h" -#include "efi.h" #include #include -#include typedef struct _SYSTEM_BOOT_ENVIRONMENT_INFORMATION { @@ -54,76 +52,6 @@ typedef struct FFSmbiosBios static_assert(offsetof(FFSmbiosBios, ExtendedBiosRomSize) == 0x18, "FFSmbiosBios: Wrong struct alignment"); -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 *detectBootmgr(FFstrbuf *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"; - - FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; - uint32_t descLen = 0; - while (efiOption->Description[descLen]) ++descLen; - - 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 - ffUcs2ToUtf8((uint16_t*) filePathList->SpecificDevicePathData, result); - return NULL; - } - } - - if (!result->length) ffUcs2ToUtf8(efiOption->Description, result); - return NULL; -} - -const char *detectSecureBoot(bool* 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) - return "RegGetValueW(HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Control\\SecureBoot\\State) failed"; - *result = !!uefiSecureBootEnabled; - return NULL; -} - const char* ffDetectBios(FFBiosResult* bios) { const FFSmbiosHeaderTable* smbiosTable = ffGetSmbiosHeaderTable(); @@ -157,12 +85,6 @@ const char* ffDetectBios(FFBiosResult* bios) case FirmwareTypeUefi: ffStrbufSetStatic(&bios->type, "UEFI"); break; default: break; } - - if (sbei.FirmwareType == FirmwareTypeUefi) - { - detectSecureBoot(&bios->secureBoot); - detectBootmgr(&bios->bootmgr); - } } return NULL; diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 9989b60cc..5816a39c4 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -4,7 +4,7 @@ #include "modules/bios/bios.h" #include "util/stringUtils.h" -#define FF_BIOS_NUM_FORMAT_ARGS 7 +#define FF_BIOS_NUM_FORMAT_ARGS 5 void ffPrintBios(FFBiosOptions* options) { @@ -14,8 +14,6 @@ void ffPrintBios(FFBiosOptions* options) ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); ffStrbufInit(&bios.type); - ffStrbufInit(&bios.bootmgr); - bios.secureBoot = false; const char* error = ffDetectBios(&bios); @@ -67,8 +65,6 @@ void ffPrintBios(FFBiosOptions* options) {FF_FORMAT_ARG_TYPE_STRBUF, &bios.vendor}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.version}, {FF_FORMAT_ARG_TYPE_STRBUF, &bios.type}, - {FF_FORMAT_ARG_TYPE_STRBUF, &bios.bootmgr}, - {FF_FORMAT_ARG_TYPE_BOOL, &bios.secureBoot}, })); } @@ -78,7 +74,6 @@ exit: ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); ffStrbufDestroy(&bios.type); - ffStrbufDestroy(&bios.bootmgr); } bool ffParseBiosCommandOptions(FFBiosOptions* options, const char* key, const char* value) @@ -124,8 +119,6 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut ffStrbufInit(&bios.vendor); ffStrbufInit(&bios.version); ffStrbufInit(&bios.type); - ffStrbufInit(&bios.bootmgr); - bios.secureBoot = false; const char* error = ffDetectBios(&bios); @@ -141,8 +134,6 @@ void ffGenerateBiosJsonResult(FF_MAYBE_UNUSED FFBiosOptions* options, yyjson_mut yyjson_mut_obj_add_strbuf(doc, obj, "vendor", &bios.vendor); yyjson_mut_obj_add_strbuf(doc, obj, "version", &bios.version); yyjson_mut_obj_add_strbuf(doc, obj, "type", &bios.type); - yyjson_mut_obj_add_strbuf(doc, obj, "bootmgr", &bios.bootmgr); - yyjson_mut_obj_add_bool(doc, obj, "secureBoot", bios.secureBoot); exit: ffStrbufDestroy(&bios.date); @@ -150,7 +141,6 @@ exit: ffStrbufDestroy(&bios.vendor); ffStrbufDestroy(&bios.version); ffStrbufDestroy(&bios.type); - ffStrbufDestroy(&bios.bootmgr); } void ffPrintBiosHelpFormat(void) @@ -161,8 +151,6 @@ void ffPrintBiosHelpFormat(void) "bios vendor", "bios version", "firmware type", - "Boot manager used to boot the system", - "Is secure boot enabled", })); } From 445dd94b53f0903f35989dca47eeaa6edeb53f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 15 May 2024 21:36:15 +0800 Subject: [PATCH 05/65] Bootmgr: add new module --- CMakeLists.txt | 6 + src/common/modules.c | 1 + src/detection/bios/efi.h | 47 -------- src/detection/bootmgr/bootmgr.c | 26 ++++ src/detection/bootmgr/bootmgr.h | 12 ++ src/detection/bootmgr/bootmgr_linux.c | 45 +++++++ src/detection/bootmgr/bootmgr_nosupport.c | 6 + src/detection/bootmgr/bootmgr_windows.c | 71 +++++++++++ src/detection/bootmgr/efi.h | 24 ++++ src/modules/bootmgr/bootmgr.c | 140 ++++++++++++++++++++++ src/modules/bootmgr/bootmgr.h | 9 ++ src/modules/bootmgr/option.h | 11 ++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/options/modules.c | 2 + src/options/modules.h | 1 + 16 files changed, 356 insertions(+), 47 deletions(-) delete mode 100644 src/detection/bios/efi.h create mode 100644 src/detection/bootmgr/bootmgr.c create mode 100644 src/detection/bootmgr/bootmgr.h create mode 100644 src/detection/bootmgr/bootmgr_linux.c create mode 100644 src/detection/bootmgr/bootmgr_nosupport.c create mode 100644 src/detection/bootmgr/bootmgr_windows.c create mode 100644 src/detection/bootmgr/efi.h create mode 100644 src/modules/bootmgr/bootmgr.c create mode 100644 src/modules/bootmgr/bootmgr.h create mode 100644 src/modules/bootmgr/option.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 735998c1a..6cb1445dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 @@ -520,6 +523,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_nosupport.c src/detection/brightness/brightness_bsd.c src/detection/chassis/chassis_bsd.c src/detection/cpu/cpu_bsd.c @@ -588,6 +592,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_nosupport.c src/detection/brightness/brightness_apple.c src/detection/chassis/chassis_nosupport.c src/detection/cpu/cpu_apple.c @@ -647,6 +652,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 diff --git a/src/common/modules.c b/src/common/modules.c index ea9958eb3..84a22658d 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -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, diff --git a/src/detection/bios/efi.h b/src/detection/bios/efi.h deleted file mode 100644 index 3878954bd..000000000 --- a/src/detection/bios/efi.h +++ /dev/null @@ -1,47 +0,0 @@ -#include "fastfetch.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; - -uint8_t ffEvBits(uint16_t val, uint8_t mask, uint8_t shift) -{ - return (uint8_t) ((val & (mask << shift)) >> shift); -} - -static void ffUcs2ToUtf8(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 | ffEvBits(chars[i], 0x1f, 6))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); - } - else - { - ffStrbufAppendC(result, (char) (0xe0 | ffEvBits(chars[i], 0xf, 12))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 6))); - ffStrbufAppendC(result, (char) (0x80 | ffEvBits(chars[i], 0x3f, 0))); - } - } -} - -#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" diff --git a/src/detection/bootmgr/bootmgr.c b/src/detection/bootmgr/bootmgr.c new file mode 100644 index 000000000..ad38d4bd8 --- /dev/null +++ b/src/detection/bootmgr/bootmgr.c @@ -0,0 +1,26 @@ +#include "efi.h" + +static inline uint8_t evBits(uint16_t val, uint8_t mask, uint8_t shift) +{ + return (uint8_t) ((val & (mask << shift)) >> shift); +} + +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))); + } + } +} diff --git a/src/detection/bootmgr/bootmgr.h b/src/detection/bootmgr/bootmgr.h new file mode 100644 index 000000000..082149e8e --- /dev/null +++ b/src/detection/bootmgr/bootmgr.h @@ -0,0 +1,12 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFBootmgrResult +{ + FFstrbuf name; + FFstrbuf firmware; + bool secureBoot; +} FFBootmgrResult; + +const char* ffDetectBootmgr(FFBootmgrResult* bios); diff --git a/src/detection/bootmgr/bootmgr_linux.c b/src/detection/bootmgr/bootmgr_linux.c new file mode 100644 index 000000000..dda5f5e90 --- /dev/null +++ b/src/detection/bootmgr/bootmgr_linux.c @@ -0,0 +1,45 @@ +#include "bootmgr.h" +#include "common/io/io.h" +#include "efi.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####"; + + FFEfiLoadOption *efiOption = (FFEfiLoadOption *)&buffer[4]; + 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); + break; + } + } + + if (ffReadFileData(FF_EFIVARS_PATH_PREFIX "SecureBoot-" FF_EFI_GLOBAL_GUID, sizeof(buffer), buffer) == 6) + result->secureBoot = buffer[4] == 1; + + return NULL; +} diff --git a/src/detection/bootmgr/bootmgr_nosupport.c b/src/detection/bootmgr/bootmgr_nosupport.c new file mode 100644 index 000000000..a61cce63b --- /dev/null +++ b/src/detection/bootmgr/bootmgr_nosupport.c @@ -0,0 +1,6 @@ +#include "bootmgr.h" + +const char* ffDetectBootmgr(FF_MAYBE_UNUSED FFBootmgrResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/bootmgr/bootmgr_windows.c b/src/detection/bootmgr/bootmgr_windows.c new file mode 100644 index 000000000..5aed4296b --- /dev/null +++ b/src/detection/bootmgr/bootmgr_windows.c @@ -0,0 +1,71 @@ +#include "bootmgr.h" +#include "efi.h" + +#include + +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"; + + FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; + 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); + break; + } + } + + 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; +} diff --git a/src/detection/bootmgr/efi.h b/src/detection/bootmgr/efi.h new file mode 100644 index 000000000..584915d1f --- /dev/null +++ b/src/detection/bootmgr/efi.h @@ -0,0 +1,24 @@ +#include "fastfetch.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; + +void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result); + +#define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c new file mode 100644 index 000000000..7e1a2d480 --- /dev/null +++ b/src/modules/bootmgr/bootmgr.c @@ -0,0 +1,140 @@ +#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); + ffStrbufSubstrBeforeLastC(&firmwareName, '.'); + ffStrbufSubstrAfterLastC(&firmwareName, '\\'); + + 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 boot manager name, firmware, etc", + ffParseBootmgrCommandOptions, + ffParseBootmgrJsonObject, + ffPrintBootmgr, + ffGenerateBootmgrJsonResult, + ffPrintBootmgrHelpFormat, + ffGenerateBootmgrJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs); +} + +void ffDestroyBootmgrOptions(FFBootmgrOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/bootmgr/bootmgr.h b/src/modules/bootmgr/bootmgr.h new file mode 100644 index 000000000..31a3b7946 --- /dev/null +++ b/src/modules/bootmgr/bootmgr.h @@ -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); diff --git a/src/modules/bootmgr/option.h b/src/modules/bootmgr/option.h new file mode 100644 index 000000000..04a7d3cc5 --- /dev/null +++ b/src/modules/bootmgr/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFBootmgrOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFBootmgrOptions; diff --git a/src/modules/modules.h b/src/modules/modules.h index 7bb11f8b2..50c2a4e96 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -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" diff --git a/src/modules/options.h b/src/modules/options.h index cfcf931d0..3972eff1b 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -6,6 +6,7 @@ #include "modules/bios/option.h" #include "modules/bluetooth/option.h" #include "modules/board/option.h" +#include "modules/bootmgr/option.h" #include "modules/break/option.h" #include "modules/brightness/option.h" #include "modules/camera/option.h" diff --git a/src/options/modules.c b/src/options/modules.c index d3a501c32..77653becd 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -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); diff --git a/src/options/modules.h b/src/options/modules.h index dcd6e5bdc..3d5597e31 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -8,6 +8,7 @@ typedef struct FFOptionsModules FFBiosOptions bios; FFBluetoothOptions bluetooth; FFBoardOptions board; + FFBootmgrOptions bootmgr; FFBreakOptions break_; FFBrightnessOptions brightness; FFCPUOptions cpu; From 49080c5361cf38e0676a3ff965d8b006cd3f0ba2 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 16 May 2024 10:59:10 +0800 Subject: [PATCH 06/65] Bootmgr (FreeBSD): add support Requires root permission --- CMakeLists.txt | 2 +- src/detection/bootmgr/bootmgr_bsd.c | 61 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/detection/bootmgr/bootmgr_bsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 6cb1445dd..d8a6591b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -523,7 +523,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_nosupport.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 diff --git a/src/detection/bootmgr/bootmgr_bsd.c b/src/detection/bootmgr/bootmgr_bsd.c new file mode 100644 index 000000000..180a66070 --- /dev/null +++ b/src/detection/bootmgr/bootmgr_bsd.c @@ -0,0 +1,61 @@ +#include "bootmgr.h" +#include "efi.h" +#include "common/io/io.h" + +#include +#include +#include + +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"; + + char hex[5]; + snprintf(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"; + + FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; + 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); + break; + } + } + + 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; +} From b2ea5d8f3e3b5eaf0caec53a2b564a2a442b26c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 11:12:52 +0800 Subject: [PATCH 07/65] Bootmgr: reuse shared code --- src/detection/bootmgr/bootmgr.c | 28 +++++++++++++++++-- src/detection/bootmgr/bootmgr_bsd.c | 22 ++------------- src/detection/bootmgr/bootmgr_linux.c | 22 ++------------- src/detection/bootmgr/bootmgr_windows.c | 22 ++------------- src/detection/bootmgr/{efi.h => efi_helper.h} | 4 +-- 5 files changed, 34 insertions(+), 64 deletions(-) rename src/detection/bootmgr/{efi.h => efi_helper.h} (85%) diff --git a/src/detection/bootmgr/bootmgr.c b/src/detection/bootmgr/bootmgr.c index ad38d4bd8..9d4dfa838 100644 --- a/src/detection/bootmgr/bootmgr.c +++ b/src/detection/bootmgr/bootmgr.c @@ -1,11 +1,11 @@ -#include "efi.h" +#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); } -void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result) +static void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result) { for (uint32_t i = 0; chars[i]; i++) { @@ -24,3 +24,27 @@ void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result) } } } + +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; +} diff --git a/src/detection/bootmgr/bootmgr_bsd.c b/src/detection/bootmgr/bootmgr_bsd.c index 180a66070..77d4e6a43 100644 --- a/src/detection/bootmgr/bootmgr_bsd.c +++ b/src/detection/bootmgr/bootmgr_bsd.c @@ -1,5 +1,5 @@ #include "bootmgr.h" -#include "efi.h" +#include "efi_helper.h" #include "common/io/io.h" #include @@ -31,25 +31,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize == sizeof(buffer)) return "ioctl(EFIIOC_VAR_GET, Boot####) failed"; - FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; - 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); - break; - } - } + ffEfiFillLoadOption((FFEfiLoadOption *)buffer, result); ioc.name = (efi_char[]){ 'S', 'e', 'c', 'u', 'r', 'e', 'B', 'o', 'o', 't', '\0' }; ioc.namesize = sizeof("SecureBoot") * 2; diff --git a/src/detection/bootmgr/bootmgr_linux.c b/src/detection/bootmgr/bootmgr_linux.c index dda5f5e90..e1e11f967 100644 --- a/src/detection/bootmgr/bootmgr_linux.c +++ b/src/detection/bootmgr/bootmgr_linux.c @@ -1,6 +1,6 @@ #include "bootmgr.h" #include "common/io/io.h" -#include "efi.h" +#include "efi_helper.h" #define FF_EFIVARS_PATH_PREFIX "/sys/firmware/efi/efivars/" @@ -18,25 +18,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) if (size < 5 + (int) sizeof(FFEfiLoadOption) || size == (ssize_t) sizeof(buffer)) return "Failed to read efivar: Boot####"; - FFEfiLoadOption *efiOption = (FFEfiLoadOption *)&buffer[4]; - 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); - break; - } - } + 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; diff --git a/src/detection/bootmgr/bootmgr_windows.c b/src/detection/bootmgr/bootmgr_windows.c index 5aed4296b..e3c687d02 100644 --- a/src/detection/bootmgr/bootmgr_windows.c +++ b/src/detection/bootmgr/bootmgr_windows.c @@ -1,5 +1,5 @@ #include "bootmgr.h" -#include "efi.h" +#include "efi_helper.h" #include @@ -43,25 +43,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) if (size < sizeof(FFEfiLoadOption) || size == sizeof(buffer)) return "GetFirmwareEnvironmentVariableW(Boot####) failed"; - FFEfiLoadOption *efiOption = (FFEfiLoadOption *)buffer; - 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); - break; - } - } + 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) diff --git a/src/detection/bootmgr/efi.h b/src/detection/bootmgr/efi_helper.h similarity index 85% rename from src/detection/bootmgr/efi.h rename to src/detection/bootmgr/efi_helper.h index 584915d1f..d650c8e97 100644 --- a/src/detection/bootmgr/efi.h +++ b/src/detection/bootmgr/efi_helper.h @@ -1,4 +1,4 @@ -#include "fastfetch.h" +#include "bootmgr.h" // https://uefi.org/specs/UEFI/2.10/10_Protocols_Device_Path_Protocol.html#generic-device-path-structures typedef struct ffEfiDevicePathProtocol @@ -19,6 +19,6 @@ typedef struct FFEfiLoadOption // uint8_t OptionalData[]; } FFEfiLoadOption; -void ffEfiUcs2ToUtf8(const uint16_t *const chars, FFstrbuf* result); +bool ffEfiFillLoadOption(const FFEfiLoadOption* efiOption, FFBootmgrResult* result); #define FF_EFI_GLOBAL_GUID "8be4df61-93ca-11d2-aa0d-00e098032b8c" From 72138dbde5cd1d9c8326a1efb71b1eb13fcc16d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 16:27:37 +0800 Subject: [PATCH 08/65] Bootmgr (macOS): add support --- CMakeLists.txt | 2 +- src/detection/bootmgr/bootmgr_apple.c | 12 ++++++++++++ src/modules/bootmgr/bootmgr.c | 5 ++++- 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 src/detection/bootmgr/bootmgr_apple.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d8a6591b7..29c432b8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -592,7 +592,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_nosupport.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 diff --git a/src/detection/bootmgr/bootmgr_apple.c b/src/detection/bootmgr/bootmgr_apple.c new file mode 100644 index 000000000..bd4c5dc98 --- /dev/null +++ b/src/detection/bootmgr/bootmgr_apple.c @@ -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; +} diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index 7e1a2d480..ac6ef5e39 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -22,8 +22,11 @@ void ffPrintBootmgr(FFBootmgrOptions* options) } FF_STRBUF_AUTO_DESTROY firmwareName = ffStrbufCreateCopy(&bootmgr.firmware); - ffStrbufSubstrBeforeLastC(&firmwareName, '.'); + #ifndef __APPLE__ ffStrbufSubstrAfterLastC(&firmwareName, '\\'); + #else + ffStrbufSubstrAfterLastC(&firmwareName, '/'); + #endif if(options->moduleArgs.outputFormat.length == 0) { From 462c3b0e061f2f6c32620d55ea24684e46fac0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 16:37:57 +0800 Subject: [PATCH 09/65] Bios / Bootmgr: update descriptions --- src/modules/bios/bios.c | 2 +- src/modules/bootmgr/bootmgr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/bios/bios.c b/src/modules/bios/bios.c index 5816a39c4..3e9b73289 100644 --- a/src/modules/bios/bios.c +++ b/src/modules/bios/bios.c @@ -159,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, diff --git a/src/modules/bootmgr/bootmgr.c b/src/modules/bootmgr/bootmgr.c index ac6ef5e39..497c0d940 100644 --- a/src/modules/bootmgr/bootmgr.c +++ b/src/modules/bootmgr/bootmgr.c @@ -126,7 +126,7 @@ void ffInitBootmgrOptions(FFBootmgrOptions* options) ffOptionInitModuleBaseInfo( &options->moduleInfo, FF_BOOTMGR_MODULE_NAME, - "Print boot manager name, firmware, etc", + "Print information of 2nd-stage bootloader (name, firmware, etc)", ffParseBootmgrCommandOptions, ffParseBootmgrJsonObject, ffPrintBootmgr, From b6a703bd56c2103bebfb8fc20c421f4b9efa040b Mon Sep 17 00:00:00 2001 From: SpoinkOSDevs Date: Thu, 16 May 2024 03:44:01 -0500 Subject: [PATCH 10/65] Logo (builtin): Add SpoinkOS Logo [FIXED!] (#925) * Update builtin.c * Create spoinkos.txt * Fix coding style * Remove left padding --------- Co-authored-by: Carter Li --- src/logo/ascii/spoinkos.txt | 5 +++++ src/logo/builtin.c | 7 +++++++ 2 files changed, 12 insertions(+) create mode 100644 src/logo/ascii/spoinkos.txt diff --git a/src/logo/ascii/spoinkos.txt b/src/logo/ascii/spoinkos.txt new file mode 100644 index 000000000..054b004bf --- /dev/null +++ b/src/logo/ascii/spoinkos.txt @@ -0,0 +1,5 @@ + @..@ + (----) + ( >__< ) + ^^ ~~ ^^ +| Spoink! | diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 2eb7e59ab..89c5dbb80 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3821,6 +3821,13 @@ 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"}, From 60fa7946f5104e488eafe41b8a577bf834dc98f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 18:30:40 +0800 Subject: [PATCH 11/65] Logo (Builtin): fix build --- src/logo/builtin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 89c5dbb80..dd8007809 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -3827,7 +3827,8 @@ static const FFlogo S[] = { .lines = FASTFETCH_DATATEXT_LOGO_SPOINKOS, .colors = { FF_COLOR_FG_GREEN, - }, + }, + }, // Slackel { .names = {"Slackel"}, From bc76220a5b45c87bcb68eb1985d2eb582c68dd5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 18:48:17 +0800 Subject: [PATCH 12/65] Doc: update JSON schema [ci skip] --- doc/json_schema.json | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/json_schema.json b/doc/json_schema.json index dc43ff932..91ae40437 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -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" From b3886c6c47df9ae00bf58ce071f9fa851e36260e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 21:57:37 +0800 Subject: [PATCH 13/65] Doc: update FAQ section [ci skip] --- README.md | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f2087551d..c9c523950 100644 --- a/README.md +++ b/README.md @@ -101,11 +101,41 @@ 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: +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! + +The local IP has nothing to do with privacy. [See discussion here](https://github.com/fastfetch-cli/fastfetch/issues/923) + +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 is 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? + +[Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema), but too long don't read. Instead, 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 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: 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 From 5ea2b2ecc9b6fbb60cbd16ff16359a354cd83353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 23:26:07 +0800 Subject: [PATCH 14/65] Doc: update FAQ [ci skip] --- README.md | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c9c523950..a27292217 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Logos can be heavily customized too; see the [logo documentation](https://github ### Q: Fastfetch shows my local IP address. It leaks my privacy! -The local IP has nothing to do with privacy. [See discussion here](https://github.com/fastfetch-cli/fastfetch/issues/923) +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. @@ -132,6 +132,25 @@ Alternatively, you can refer to the presets in [`presets` directory](https://git Try `fastfetch -l /path/to/logo`. See [logo documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Logo-options) for detail. +### 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). From def758580f0da34d1d297a68a9960620ddd4a921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 23:34:40 +0800 Subject: [PATCH 15/65] Doc: update FAQ [ci skip] --- README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/README.md b/README.md index a27292217..b40b156da 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,24 @@ If you really don't like it, you can disable the `Local IP` module in `config.js Alternatively, you can refer to the presets in [`presets` directory](https://github.com/fastfetch-cli/fastfetch/tree/dev/presets). +### 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 -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. From b4a6606faf75ad679293e2aa29319a9c307ec016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 16 May 2024 23:47:25 +0800 Subject: [PATCH 16/65] Doc: update FAQ [ci skip] --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b40b156da..0bde8cf53 100644 --- a/README.md +++ b/README.md @@ -120,14 +120,18 @@ If you really don't like it, you can disable the `Local IP` module in `config.js ### 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 is saved in `~/.config/fastfetch/config.jsonc` by default. See [Wiki for detail](https://github.com/fastfetch-cli/fastfetch/wiki/Configuration). +`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? -[Here is the documentation](https://github.com/fastfetch-cli/fastfetch/wiki/Json-Schema), but too long don't read. Instead, use an IDE with JSON schema support (like VSCode) to edit it. +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 @@ -141,6 +145,7 @@ Fastfetch uses `format` to generate output. For example to make `GPU` module sho } ] } +``` which is equivalent to `fastfetch -s gpu --gpu-format '{2}'` From 06b2ff9a08a54edeb4993062c8f1fa6bdb7502f7 Mon Sep 17 00:00:00 2001 From: Anonyzard <52675980+Anonyzard@users.noreply.github.com> Date: Thu, 16 May 2024 22:19:26 -0300 Subject: [PATCH 17/65] Add Loc-OS Linux support (#926) * Logo (Builtin): add Loc-OS * Packages (Linux): add lpkg and lpkgbuild detection --- src/detection/os/os_linux.c | 7 +++++++ src/detection/packages/packages.h | 2 ++ src/detection/packages/packages_linux.c | 2 ++ src/logo/ascii/locos.txt | 18 ++++++++++++++++++ src/logo/builtin.c | 12 ++++++++++++ src/modules/packages/option.h | 2 ++ src/modules/packages/packages.c | 20 ++++++++++++++++++-- 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 src/logo/ascii/locos.txt diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 2e8d3bc92..3378b5d35 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -156,6 +156,13 @@ 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->name, "Loc-OS Linux"); // (ffStrbufEqualS(&os->id, "MX") + ffStrbufSetS(&result->id, "locos"); + ffStrbufSetS(&result->idLike, "debian"); + return true; + } else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE)) { ffStrbufSetS(&result->id, "pve"); diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index d8983242a..4e954b96a 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -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; diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 0e19043a4..73920097f 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -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); diff --git a/src/logo/ascii/locos.txt b/src/logo/ascii/locos.txt new file mode 100644 index 000000000..cbcb5be8a --- /dev/null +++ b/src/logo/ascii/locos.txt @@ -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. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index dd8007809..3df2b1a22 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -2385,6 +2385,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"}, diff --git a/src/modules/packages/option.h b/src/modules/packages/option.h index 66d332d5d..f294b916c 100644 --- a/src/modules/packages/option.h +++ b/src/modules/packages/option.h @@ -28,6 +28,8 @@ typedef enum FFPackagesFlags FF_PACKAGES_FLAG_XBPS_BIT = 1 << 18, FF_PACKAGES_FLAG_AM_BIT = 1 << 19, FF_PACKAGES_FLAG_SORCERY_BIT = 1 << 20, + FF_PACKAGES_FLAG_LPKG_BIT = 1 << 21, + FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22, } FFPackagesFlags; typedef struct FFPackagesOptions diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 52ab6906d..f9ccd9258 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 30 +#define FF_PACKAGES_NUM_FORMAT_ARGS 32 void ffPrintPackages(FFPackagesOptions* options) { @@ -47,6 +47,8 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE(emerge) FF_PRINT_PACKAGE(eopkg) FF_PRINT_PACKAGE(xbps) + FF_PRINT_PACKAGE(lpkg) + FF_PRINT_PACKAGE(lpkgbuild) FF_PRINT_PACKAGE_NAME(nixSystem, "nix-system") FF_PRINT_PACKAGE_NAME(nixUser, "nix-user") FF_PRINT_PACKAGE_NAME(nixDefault, "nix-default") @@ -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} (lpkg), {15} (lpkgbuild), {16} (flatpak-system), {17} (flatpack-user), {18} (snap), {19} (brew), {20} (brew-cask), {21} (MacPorts), {22} (scoop), {23} (choco), {24} (pkgtool), {25} (paludis), {26} (winget), {27} (opkg), {28} (am), {29} (sorcery)", FF_PACKAGES_NUM_FORMAT_ARGS, ((const char* []) { "Number of all packages", "Number of pacman packages", "Pacman branch on manjaro", @@ -393,6 +407,8 @@ void ffPrintPackagesHelpFormat(void) "Number of nix-default packages", "Number of apk packages", "Number of pkg packages", + "Number of lpkg packages", + "Number of lpkgbuild packages", "Number of flatpak-system packages", "Number of flatpak-user packages", "Number of snap packages", From 965ab1abc40c80f4499c46ad4cde78d311db9780 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 09:28:17 +0800 Subject: [PATCH 18/65] Packages: don't break existing config --- src/detection/os/os_linux.c | 11 +++++------ src/modules/packages/packages.c | 10 +++++----- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index 3378b5d35..a0831e643 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -157,12 +157,11 @@ static bool detectDebianDerived(FFOSResult* result) return true; } else if (ffStrbufStartsWithS(&result->name, "Loc-OS")) - { - ffStrbufSetS(&result->name, "Loc-OS Linux"); // (ffStrbufEqualS(&os->id, "MX") - ffStrbufSetS(&result->id, "locos"); - ffStrbufSetS(&result->idLike, "debian"); - return true; - } + { + ffStrbufSetS(&result->id, "locos"); + ffStrbufSetS(&result->idLike, "debian"); + return true; + } else if (ffPathExists("/usr/bin/pveversion", FF_PATHTYPE_FILE)) { ffStrbufSetS(&result->id, "pve"); diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index f9ccd9258..229e1f43c 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -47,8 +47,6 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE(emerge) FF_PRINT_PACKAGE(eopkg) FF_PRINT_PACKAGE(xbps) - FF_PRINT_PACKAGE(lpkg) - FF_PRINT_PACKAGE(lpkgbuild) FF_PRINT_PACKAGE_NAME(nixSystem, "nix-system") FF_PRINT_PACKAGE_NAME(nixUser, "nix-user") FF_PRINT_PACKAGE_NAME(nixDefault, "nix-default") @@ -68,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'); } @@ -393,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} (lpkg), {15} (lpkgbuild), {16} (flatpak-system), {17} (flatpack-user), {18} (snap), {19} (brew), {20} (brew-cask), {21} (MacPorts), {22} (scoop), {23} (choco), {24} (pkgtool), {25} (paludis), {26} (winget), {27} (opkg), {28} (am), {29} (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,8 +407,6 @@ void ffPrintPackagesHelpFormat(void) "Number of nix-default packages", "Number of apk packages", "Number of pkg packages", - "Number of lpkg packages", - "Number of lpkgbuild packages", "Number of flatpak-system packages", "Number of flatpak-user packages", "Number of snap packages", @@ -423,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", From 289d03cfb2d12bd6f472082838bffdd9d413d293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 10:02:42 +0800 Subject: [PATCH 19/65] Kernel (Windows): detect old release code name for Windows 10 --- src/util/platform/FFPlatform_windows.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index 0ad0a62c8..bddbaf007 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -184,8 +184,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); From 02e5232bda7fd19000884d1462ec79b4a6e2457b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 13:57:07 +0800 Subject: [PATCH 20/65] TerminalShell: ignore clifm Ref: https://github.com/leo-arch/clifm/issues/289 --- src/detection/terminalshell/terminalshell_linux.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index 006f40a37..a535cfc42 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -244,6 +244,7 @@ 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 ffStrContainsIgnCase(name, "debug") || ffStrContainsIgnCase(name, "not-found") || ffStrEndsWith(name, ".sh") @@ -294,6 +295,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 From 1421627a4750f39d6fffc84c09960dc84a7b8faa Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 17 May 2024 16:14:35 +0800 Subject: [PATCH 21/65] CPU (Linux): detect core count for different core types --- src/detection/cpu/cpu.h | 2 ++ src/detection/cpu/cpu_linux.c | 52 ++++++++++++++++++++++++++++------- src/modules/cpu/cpu.c | 32 +++++++++++++-------- 3 files changed, 64 insertions(+), 22 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index bba2aba47..36755d762 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -17,6 +17,8 @@ typedef struct FFCPUResult double frequencyMax; // GHz double frequencyMin; // GHz + uint8_t coreCounts[8]; // number of P cores, E cores, etc. + double temperature; } FFCPUResult; diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index e100eb60c..0ada1f5a4 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -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) @@ -118,30 +136,41 @@ static bool detectFrequency(FFCPUResult* cpu) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); uint32_t baseLen = path.length; + uint64_t freq = (uint64_t) -1; + uint32_t ifreq = (uint32_t) -1; + struct dirent* entry; 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 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; + + if (fmax != freq) + { + freq = fmax; + ++ifreq; + } + if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) + cpu->coreCounts[ifreq] += getNumCores(&path, &buffer); } - 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; @@ -151,6 +180,9 @@ static bool detectFrequency(FFCPUResult* cpu) ffStrbufSubstrBefore(&path, baseLen); } } + cpu->frequencyBase /= 1e6; + cpu->frequencyMax /= 1e6; + cpu->frequencyMin /= 1e6; return true; } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 43ec9fe9a..7c5bee4f0 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -10,12 +10,14 @@ 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, + .name = ffStrbufCreate(), + .vendor = ffStrbufCreate() + }; const char* error = ffDetectCPU(options, &cpu); @@ -143,12 +145,14 @@ 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, + .name = ffStrbufCreate(), + .vendor = ffStrbufCreate() + }; const char* error = ffDetectCPU(options, &cpu); @@ -176,6 +180,10 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax); yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin); + yyjson_mut_val* coreCounts = yyjson_mut_obj_add_arr(doc, obj, "coreCounts"); + for (uint32_t i = 0; i < sizeof (cpu.coreCounts) && cpu.coreCounts[i] > 0; i++) + yyjson_mut_arr_add_uint(doc, coreCounts, cpu.coreCounts[i]); + yyjson_mut_obj_add_real(doc, obj, "temperature", cpu.temperature); } From ab2268a92726552c03f1836faec7ba4b13b3f2c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 16:44:53 +0800 Subject: [PATCH 22/65] CPU (macOS): detect core count for different core types --- src/detection/cpu/cpu_apple.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index de3b18707..ff7a5d304 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -55,6 +55,19 @@ static const char* detectFrequency(FFCPUResult* cpu) cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000); + int nPerfLevels = ffSysctlGetInt("hw.nperflevels", 0); + if (nPerfLevels > 0) + { + if (nPerfLevels > (int) sizeof(cpu->coreCounts)) + nPerfLevels = (int) sizeof(cpu->coreCounts); + char sysctlKey[] = "hw.perflevelN.logicalcpu"; + for (int i = 0; i < nPerfLevels; ++i) + { + sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i); + cpu->coreCounts[i] = (uint8_t) ffSysctlGetInt(sysctlKey, 0); + } + } + if (pCoreLength >= 8) { ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL); From 62bf3ec0210beeb91450c21ea7f1cde870b64e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 21:30:47 +0800 Subject: [PATCH 23/65] Util (Windows): add `nt.h` and use it --- src/detection/battery/battery_windows.c | 11 +---------- src/util/platform/FFPlatform_windows.c | 6 +----- src/util/windows/nt.h | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 15 deletions(-) create mode 100644 src/util/windows/nt.h diff --git a/src/detection/battery/battery_windows.c b/src/detection/battery/battery_windows.c index 5a0a78a3c..1d507c8c6 100644 --- a/src/detection/battery/battery_windows.c +++ b/src/detection/battery/battery_windows.c @@ -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 #include -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) diff --git a/src/util/platform/FFPlatform_windows.c b/src/util/platform/FFPlatform_windows.c index bddbaf007..d5c690c63 100644 --- a/src/util/platform/FFPlatform_windows.c +++ b/src/util/platform/FFPlatform_windows.c @@ -3,15 +3,11 @@ #include "util/stringUtils.h" #include "util/windows/unicode.h" #include "util/windows/registry.h" +#include "util/windows/nt.h" -#include #include #include -NTSTATUS NTAPI RtlGetVersion( - _Inout_ PRTL_OSVERSIONINFOW lpVersionInformation -); - static void getExePath(FFPlatform* platform) { wchar_t exePathW[MAX_PATH]; diff --git a/src/util/windows/nt.h b/src/util/windows/nt.h new file mode 100644 index 000000000..53b33169b --- /dev/null +++ b/src/util/windows/nt.h @@ -0,0 +1,25 @@ +#pragma once + +#include +#include + +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 +); From 0b94ff5adb7a934102bb53af95c497fa2dc3c784 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 21:31:24 +0800 Subject: [PATCH 24/65] CPU (Windows): detect core count of different core types --- src/detection/cpu/cpu_windows.c | 35 ++++++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 0f3bb55d5..a1f09c051 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -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,30 @@ static const char* detectByRegistry(FFCPUResult* cpu) return NULL; } +static const char* detectCoreCounts(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"; + + uint64_t freq = (uint64_t) -1; + uint32_t ifreq = (uint32_t) -1; + for (uint32_t i = 0; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) + { + if (freq != pinfo[i].MhzLimit) + { + freq = pinfo[i].MhzLimit; + ++ifreq; + } + if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) + cpu->coreCounts[ifreq]++; + } + + 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 +192,9 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (error) return error; + detectSpeedByCpuid(cpu); + detectCoreCounts(cpu); + if (cpu->frequencyMax != cpu->frequencyMax) detectMaxSpeedBySmbios(cpu); From eda949647982c4aaf91eebd5dbff8d218300c7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 17 May 2024 21:42:11 +0800 Subject: [PATCH 25/65] GPU (Windows): try removing limitation --- src/detection/gpu/gpu_windows.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index dc809727f..bd695d094 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -61,8 +61,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i) { - if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; - const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey); if (__builtin_expect(deviceKeyLength == 100, true)) { From 1118c57d8f6df115f255267d875cbeb79b586747 Mon Sep 17 00:00:00 2001 From: furretpaws <99131021+FurretDev@users.noreply.github.com> Date: Fri, 17 May 2024 18:28:34 +0200 Subject: [PATCH 26/65] Logo (Builtin): Added "Furreto Linux" support (#927) * added furreto * fixed * fix i think * Update furreto.txt Remove left padding and empty lines. Replace `${cN}` with `$N` * Update builtin.c --------- Co-authored-by: Carter Li --- src/logo/ascii/furreto.txt | 22 ++++++++++++++++++++++ src/logo/builtin.c | 11 +++++++++++ 2 files changed, 33 insertions(+) create mode 100644 src/logo/ascii/furreto.txt diff --git a/src/logo/ascii/furreto.txt b/src/logo/ascii/furreto.txt new file mode 100644 index 000000000..14ba1c1d0 --- /dev/null +++ b/src/logo/ascii/furreto.txt @@ -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. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 3df2b1a22..d6ce0af94 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1678,6 +1678,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 {}, }; From 90a242a4aa644858f60ea18d65ef14ff3c0cbdfe Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 08:24:46 +0800 Subject: [PATCH 27/65] CPU (BSD): detect max / min frequency; detect core count of different core types --- src/detection/cpu/cpu_bsd.c | 56 +++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 70623cbff..47a94ac28 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -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) + { + // + // + // 0, 1, 2, 3 + // + // + // 0, 1 + // THREAD groupSMT group + // + // + // 2, 3 + // THREAD groupSMT group + // + // + // + // + uint32_t i = 0; + while (true) + { + i = ffStrbufNextIndexS(&buffer, i, "THREAD group"); // Find physical core with hyper-threading enabled + if (i >= buffer.length) break; + cpu->coresPhysical--; + i += (uint32_t) strlen("THREAD group"); + } + } + + uint64_t freq = (uint64_t) -1; + uint32_t ifreq = (uint32_t) -1; + for (uint16_t i = 0; i < cpu->coresLogical; ++i) + { + char key[32]; + snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i); + if (ffSysctlGetString(key, &buffer) == NULL && buffer.length > 0) + { + // MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000 + uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10); + uint32_t fmin = fmax; + uint32_t i = ffStrbufLastIndexC(&buffer, ' '); + if (i < buffer.length) + fmin = (uint32_t) strtoul(buffer.chars + i + 1, NULL, 10); + if (!(cpu->frequencyMin <= fmin)) cpu->frequencyMin = fmin; // Counting for NaN + if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax; + + if (freq != fmax) + { + freq = fmax; + ++ifreq; + } + if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) + cpu->coreCounts[ifreq]++; + } + ffStrbufClear(&buffer); + } + int clockRate = ffSysctlGetInt("hw.clockrate", 0); cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0; cpu->temperature = FF_CPU_TEMP_UNSET; From 92abf3e06314ea28ab92a8361669c8492762bf75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 00:32:29 +0800 Subject: [PATCH 28/65] TerminalShell (Linux): ignore valgrind --- src/detection/terminalshell/terminalshell_linux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index a535cfc42..fbb90b207 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -245,6 +245,7 @@ static pid_t getShellInfo(FFShellResult* result, pid_t pid) 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") From fd16e69464c274682ecc4c7c7c1311fe82d25b38 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 01:46:56 +0800 Subject: [PATCH 29/65] CPU (macOS): fix core count detection --- src/detection/cpu/cpu_apple.c | 38 ++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index ff7a5d304..8c0f72827 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -55,19 +55,6 @@ static const char* detectFrequency(FFCPUResult* cpu) cpu->frequencyMin = (pMin < eMin ? pMin : eMin) / (1000.0 * 1000 * 1000); - int nPerfLevels = ffSysctlGetInt("hw.nperflevels", 0); - if (nPerfLevels > 0) - { - if (nPerfLevels > (int) sizeof(cpu->coreCounts)) - nPerfLevels = (int) sizeof(cpu->coreCounts); - char sysctlKey[] = "hw.perflevelN.logicalcpu"; - for (int i = 0; i < nPerfLevels; ++i) - { - sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i); - cpu->coreCounts[i] = (uint8_t) ffSysctlGetInt(sysctlKey, 0); - } - } - if (pCoreLength >= 8) { ffCfDictGetData(properties, CFSTR("voltage-states5-sram"), pCoreLength - 8, 4, (uint8_t*) &aMax, NULL); @@ -81,20 +68,34 @@ static const char* detectFrequency(FFCPUResult* cpu) { cpu->frequencyBase = ffSysctlGetInt64("hw.cpufrequency", 0) / 1000.0 / 1000.0 / 1000.0; cpu->frequencyMin = ffSysctlGetInt64("hw.cpufrequency_min", 0) / 1000.0 / 1000.0 / 1000.0; - cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0); - if(cpu->frequencyMax > 0.0) - cpu->frequencyMax /= 1000.0 * 1000.0 * 1000.0; - else + cpu->frequencyMax = ffSysctlGetInt64("hw.cpufrequency_max", 0) / 1000.0 / 1000.0 / 1000.0; + if(cpu->frequencyBase != cpu->frequencyBase) { unsigned current = 0; size_t size = sizeof(current); if (sysctl((int[]){ CTL_HW, HW_CPU_FREQ }, 2, ¤t, &size, NULL, 0) == 0) - cpu->frequencyMax = (double) current / 1000.0 / 1000.0 / 1000.0; + cpu->frequencyBase = (double) current / 1000.0 / 1000.0 / 1000.0; } return NULL; } #endif +static const char* detectCoreCount(FFCPUResult* cpu) +{ + int nPerfLevels = ffSysctlGetInt("hw.nperflevels", 0); + if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed"; + + if (nPerfLevels > (int) sizeof(cpu->coreCounts)) + nPerfLevels = (int) sizeof(cpu->coreCounts); + char sysctlKey[] = "hw.perflevelN.logicalcpu"; + for (int i = 0; i < nPerfLevels; ++i) + { + sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i); + cpu->coreCounts[i] = (uint8_t) ffSysctlGetInt(sysctlKey, 0); + } + return NULL; +} + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { if (ffSysctlGetString("machdep.cpu.brand_string", &cpu->name) != NULL) @@ -117,6 +118,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; From b79c47cac96de20799ae8b0e526f91d49d9c61b6 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 01:50:21 +0800 Subject: [PATCH 30/65] CPU (BSD): fix max freq detection --- src/detection/cpu/cpu_bsd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 47a94ac28..6ada85657 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -66,6 +66,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) } ffStrbufClear(&buffer); } + cpu->frequencyMin /= 1000; + cpu->frequencyMax /= 1000; int clockRate = ffSysctlGetInt("hw.clockrate", 0); cpu->frequencyBase = clockRate <= 0 ? 0.0/0.0 : clockRate / 1000.0; From 45446c1c1d4a603702a75a4e3372def983674c0d Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 16:41:30 +0800 Subject: [PATCH 31/65] Bootmgr (FreeBSD): silence compiler warnings --- src/detection/bootmgr/bootmgr_bsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/bootmgr/bootmgr_bsd.c b/src/detection/bootmgr/bootmgr_bsd.c index 77d4e6a43..86fe86fac 100644 --- a/src/detection/bootmgr/bootmgr_bsd.c +++ b/src/detection/bootmgr/bootmgr_bsd.c @@ -23,8 +23,8 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) if (ioctl(efifd, EFIIOC_VAR_GET, &ioc) < 0 || ioc.datasize != 2) return "ioctl(EFIIOC_VAR_GET, BootCurrent) failed"; - char hex[5]; - snprintf(hex, sizeof(hex), "%04X", *(uint16_t*)buffer); + 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; From 926390508eb0f9663249f68b561dd1194c3015f4 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 16:43:33 +0800 Subject: [PATCH 32/65] CPU (FreeBSD): fix core count detection --- src/detection/cpu/cpu_bsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 6ada85657..2940c2c00 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -43,6 +43,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) 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) @@ -64,7 +65,6 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) cpu->coreCounts[ifreq]++; } - ffStrbufClear(&buffer); } cpu->frequencyMin /= 1000; cpu->frequencyMax /= 1000; From f9e0efb7eec5b1d65463640afad54701a8a89dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 10:35:06 +0800 Subject: [PATCH 33/65] Smbios: improve SMBIOS data reading code --- src/util/smbiosHelper.c | 86 +++++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/src/util/smbiosHelper.c b/src/util/smbiosHelper.c index 13b119ec4..39d3e94a1 100644 --- a/src/util/smbiosHelper.c +++ b/src/util/smbiosHelper.c @@ -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); } } From 5078c8d9101016713d261c1f810da118ecc2f637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 10:39:51 +0800 Subject: [PATCH 34/65] Revert "GPU (Windows): try removing limitation" This reverts commit eda949647982c4aaf91eebd5dbff8d218300c7dd. --- src/detection/gpu/gpu_windows.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index bd695d094..dc809727f 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -61,6 +61,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* for (DWORD i = 0; EnumDisplayDevicesW(NULL, i, &displayDevice, 0); ++i) { + if (displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) continue; + const uint32_t deviceKeyLength = (uint32_t) wcslen(displayDevice.DeviceKey); if (__builtin_expect(deviceKeyLength == 100, true)) { From e9a44f71b233abf1d1d022eb1ed467f58628b267 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 11:08:21 +0800 Subject: [PATCH 35/65] Bootmgr (Android): fix compiling --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29c432b8a..5bbb3ebc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -465,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 From c763896b4961c91bd064ab1997a3ce4935052b7d Mon Sep 17 00:00:00 2001 From: Matheus Castello Date: Sat, 18 May 2024 00:57:21 -0300 Subject: [PATCH 36/65] Logo (builtin): Fix TorizonCore logo colors (#934) You can verify the colors of the logo from https://www.torizon.io/ Signed-off-by: Matheus Castello --- src/logo/builtin.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index d6ce0af94..ba8403de6 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -4075,10 +4075,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 From c04c040713d79dad8258513219cf69d07a7dba6a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 11:58:35 +0800 Subject: [PATCH 37/65] Wifi (FreeBSD): fix bssid & status detection --- src/detection/wifi/wifi_bsd.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/detection/wifi/wifi_bsd.c b/src/detection/wifi/wifi_bsd.c index 663c6a4be..66edc10c6 100644 --- a/src/detection/wifi/wifi_bsd.c +++ b/src/detection/wifi/wifi_bsd.c @@ -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); } } From 4ffa0ffcb7e13db0573eb86b14de7b3444aa24b6 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 13:09:37 +0800 Subject: [PATCH 38/65] Disk (FreeBSD): ensure createTime is inited --- src/detection/disk/disk_bsd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index dcd6cc507..84547b7ad 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -132,6 +132,8 @@ 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) From ed02845c409c37492cfb25789a269067a470aeb2 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 13:11:22 +0800 Subject: [PATCH 39/65] OS (Linux): better code name detection --- src/detection/os/os_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index a0831e643..cd4844574 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -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}, }); } From 15766f5266e54e23bba604ea3ff48e24bdfea9ca Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 18 May 2024 13:38:07 +0800 Subject: [PATCH 40/65] Disk (BSD): dont set createTime if stat fails to detect it --- src/detection/disk/disk_bsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 84547b7ad..446e2e610 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -140,7 +140,7 @@ const char* ffDetectDisksImpl(FFDiskOptions* options, FFlist* disks) 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)); } From 7946e69a665436628142a1262a5ec421b9d99d29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 09:58:04 +0800 Subject: [PATCH 41/65] CPU: print core count for different core types --- src/detection/cpu/cpu.h | 8 ++++++- src/detection/cpu/cpu_apple.c | 7 +++--- src/detection/cpu/cpu_bsd.c | 11 +++++---- src/detection/cpu/cpu_linux.c | 16 ++++++------- src/detection/cpu/cpu_windows.c | 19 ++++++++-------- src/modules/cpu/cpu.c | 40 ++++++++++++++++++++++++++------- 6 files changed, 64 insertions(+), 37 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 36755d762..982310cdb 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -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; @@ -17,7 +23,7 @@ typedef struct FFCPUResult double frequencyMax; // GHz double frequencyMin; // GHz - uint8_t coreCounts[8]; // number of P cores, E cores, etc. + FFCPUCore coreTypes[8]; // number of P cores, E cores, etc. double temperature; } FFCPUResult; diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 8c0f72827..85e06cde2 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -85,13 +85,14 @@ static const char* detectCoreCount(FFCPUResult* cpu) int nPerfLevels = ffSysctlGetInt("hw.nperflevels", 0); if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed"; - if (nPerfLevels > (int) sizeof(cpu->coreCounts)) - nPerfLevels = (int) sizeof(cpu->coreCounts); char sysctlKey[] = "hw.perflevelN.logicalcpu"; for (int i = 0; i < nPerfLevels; ++i) { sysctlKey[strlen("hw.perflevel")] = (char) ('0' + i); - cpu->coreCounts[i] = (uint8_t) ffSysctlGetInt(sysctlKey, 0); + cpu->coreTypes[i < (int) sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]) : i : (int) sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]) - 1] = { + .freq = nPerfLevels - i, + .count = ffSysctlGetInt(sysctlKey, 0), + } } return NULL; } diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 2940c2c00..2310ac432 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -39,7 +39,6 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) } } - uint64_t freq = (uint64_t) -1; uint32_t ifreq = (uint32_t) -1; for (uint16_t i = 0; i < cpu->coresLogical; ++i) { @@ -57,13 +56,13 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (!(cpu->frequencyMin <= fmin)) cpu->frequencyMin = fmin; // Counting for NaN if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax; - if (freq != fmax) + if (cpu->coreTypes[ifreq].freq != fmax) { - freq = fmax; - ++ifreq; + if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) + ++ifreq; + cpu->coreTypes[ifreq].freq = fmax; } - if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) - cpu->coreCounts[ifreq]++; + cpu->coreTypes[ifreq].count++; } } cpu->frequencyMin /= 1000; diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 0ada1f5a4..fdcd2e3e3 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -136,11 +136,9 @@ static bool detectFrequency(FFCPUResult* cpu) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); uint32_t baseLen = path.length; - uint64_t freq = (uint64_t) -1; - uint32_t ifreq = (uint32_t) -1; - + uint32_t ifreq = 0; 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")])) { @@ -161,13 +159,13 @@ static bool detectFrequency(FFCPUResult* cpu) else cpu->frequencyMax = fmax; - if (fmax != freq) + if (cpu->coreTypes[ifreq].freq != fmax) { - freq = fmax; - ++ifreq; + if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) + ++ifreq; + cpu->coreTypes[ifreq].freq = fmax; } - if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) - cpu->coreCounts[ifreq] += getNumCores(&path, &buffer); + cpu->coreTypes[ifreq].count += getNumCores(&path, &buffer); } uint32_t fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer); if (fmin > 0) diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index a1f09c051..2c7ce6beb 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -160,23 +160,22 @@ static const char* detectByRegistry(FFCPUResult* cpu) return NULL; } -static const char* detectCoreCounts(FFCPUResult* cpu) +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"; - uint64_t freq = (uint64_t) -1; - uint32_t ifreq = (uint32_t) -1; - for (uint32_t i = 0; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) + uint32_t ifreq = 0; + for (uint32_t i = 1; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) { - if (freq != pinfo[i].MhzLimit) + if (cpu->coreTypes[ifreq].freq != pinfo[i].MhzLimit) { - freq = pinfo[i].MhzLimit; - ++ifreq; + if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) + ++ifreq; + cpu->coreTypes[ifreq].freq = pinfo[i].MhzLimit; } - if (__builtin_expect(ifreq < sizeof(cpu->coreCounts), true)) - cpu->coreCounts[ifreq]++; + cpu->coreTypes[ifreq].count++; } if (cpu->frequencyBase != cpu->frequencyBase) @@ -193,7 +192,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) return error; detectSpeedByCpuid(cpu); - detectCoreCounts(cpu); + detectCoreTypes(cpu); if (cpu->frequencyMax != cpu->frequencyMax) detectMaxSpeedBySmbios(cpu); diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 7c5bee4f0..c75e679be 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -6,7 +6,12 @@ #include "modules/cpu/cpu.h" #include "util/stringUtils.h" -#define FF_CPU_NUM_FORMAT_ARGS 8 +#define FF_CPU_NUM_FORMAT_ARGS 9 + +static int sortCores(const FFCPUCore* a, const FFCPUCore* b) +{ + return (int)b->freq - (int)a->freq; +} void ffPrintCPU(FFCPUOptions* options) { @@ -51,9 +56,9 @@ void ffPrintCPU(FFCPUOptions* options) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); double freq = cpu.frequencyMax; - if(freq != freq) + 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 @@ -66,6 +71,19 @@ void ffPrintCPU(FFCPUOptions* options) } else { + FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate(); + uint32_t typeCount = 0; + while (cpu.coreTypes[typeCount].count != 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); + 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[]){ @@ -76,7 +94,8 @@ void ffPrintCPU(FFCPUOptions* options) {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_STRBUF, &tempStr}, + {FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes}, })); } } @@ -180,9 +199,13 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_obj_add_real(doc, frequency, "max", cpu.frequencyMax); yyjson_mut_obj_add_real(doc, frequency, "min", cpu.frequencyMin); - yyjson_mut_val* coreCounts = yyjson_mut_obj_add_arr(doc, obj, "coreCounts"); - for (uint32_t i = 0; i < sizeof (cpu.coreCounts) && cpu.coreCounts[i] > 0; i++) - yyjson_mut_arr_add_uint(doc, coreCounts, cpu.coreCounts[i]); + 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); } @@ -201,7 +224,8 @@ void ffPrintCPUHelpFormat(void) "Online core count", "Base frequency", "Max frequency", - "Temperature (formatted)" + "Temperature (formatted)", + "Logical core count grouped by frequency", })); } From d88e2eeb36502aec598ae33540edd1c4a4baf404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 18:22:32 +0800 Subject: [PATCH 42/65] CPU (macOS): fix compiling --- src/detection/cpu/cpu_apple.c | 12 +++++++----- src/modules/cpu/cpu.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index 85e06cde2..efffa6d41 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -82,17 +82,19 @@ static const char* detectFrequency(FFCPUResult* cpu) static const char* detectCoreCount(FFCPUResult* cpu) { - int nPerfLevels = ffSysctlGetInt("hw.nperflevels", 0); + uint32_t nPerfLevels = (uint32_t) ffSysctlGetInt("hw.nperflevels", 0); if (nPerfLevels <= 0) return "sysctl(hw.nperflevels) failed"; char sysctlKey[] = "hw.perflevelN.logicalcpu"; - for (int i = 0; i < nPerfLevels; ++i) + 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 < (int) sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]) : i : (int) sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0]) - 1] = { + cpu->coreTypes[i] = (FFCPUCore) { .freq = nPerfLevels - i, - .count = ffSysctlGetInt(sysctlKey, 0), - } + .count = (uint32_t) ffSysctlGetInt(sysctlKey, 0), + }; } return NULL; } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index c75e679be..16692c508 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -73,7 +73,7 @@ void ffPrintCPU(FFCPUOptions* options) { FF_STRBUF_AUTO_DESTROY coreTypes = ffStrbufCreate(); uint32_t typeCount = 0; - while (cpu.coreTypes[typeCount].count != 0) typeCount++; + 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); From 14969b31d0667b852a2b935bf728ba60a92608a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 18 May 2024 20:53:11 +0800 Subject: [PATCH 43/65] CPU (Windows): fix silly mistake --- src/detection/cpu/cpu_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 2c7ce6beb..56cd5c839 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -167,7 +167,7 @@ static const char* detectCoreTypes(FFCPUResult* cpu) return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed"; uint32_t ifreq = 0; - for (uint32_t i = 1; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) + for (uint32_t i = 0; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) { if (cpu->coreTypes[ifreq].freq != pinfo[i].MhzLimit) { From 758ddae3449b0a72bf95b7d7e6dc02cfddd66535 Mon Sep 17 00:00:00 2001 From: Shu Niu Date: Sun, 19 May 2024 09:31:08 +0800 Subject: [PATCH 44/65] macOS: Add support for old MacOS version (#936) * Add support for old MacOS version, fix-1. * Add support for old MacOS version, fix-2. * Add support for old MacOS version with fixing metal gpu api. * Update disk_bsd.c * Update disk_bsd.c * Update gpu_apple.m * Update monitor_apple.m * Update os_apple.m * Update wifi_apple.m * Update camera_apple.m * Update camera_apple.m --------- Co-authored-by: Carter Li --- src/detection/camera/camera_apple.m | 5 +++- src/detection/disk/disk_bsd.c | 4 ++++ .../displayserver/displayserver_apple.c | 18 +++++++++++++++ src/detection/font/font_apple.m | 4 ++++ src/detection/gpu/gpu_apple.m | 19 +++++++++++---- src/detection/monitor/monitor_apple.m | 23 ++++++++++++++++++- src/detection/os/os_apple.m | 3 +-- .../physicaldisk/physicaldisk_apple.c | 12 +++++++++- .../terminalshell/terminalshell_linux.c | 4 ++++ src/detection/wifi/wifi_apple.m | 6 ++--- 10 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/detection/camera/camera_apple.m b/src/detection/camera/camera_apple.m index 66e18a7d6..ab15fb99e 100644 --- a/src/detection/camera/camera_apple.m +++ b/src/detection/camera/camera_apple.m @@ -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 } diff --git a/src/detection/disk/disk_bsd.c b/src/detection/disk/disk_bsd.c index 446e2e610..3046a3577 100644 --- a/src/detection/disk/disk_bsd.c +++ b/src/detection/disk/disk_bsd.c @@ -66,6 +66,10 @@ static void detectFsInfo(struct statfs* fs, FFDisk* disk) #include #include +#ifndef MAC_OS_X_VERSION_10_15 + #define MNT_REMOVABLE 0x00000200 +#endif + struct CmnAttrBuf { uint32_t length; attrreference_t nameRef; diff --git a/src/detection/displayserver/displayserver_apple.c b/src/detection/displayserver/displayserver_apple.c index 3a63fb303..964a6981f 100644 --- a/src/detection/displayserver/displayserver_apple.c +++ b/src/detection/displayserver/displayserver_apple.c @@ -8,6 +8,10 @@ #include extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); +#ifndef MAC_OS_X_VERSION_10_15 +#import +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), diff --git a/src/detection/font/font_apple.m b/src/detection/font/font_apple.m index 9a9888e5f..683acad03 100644 --- a/src/detection/font/font_apple.m +++ b/src/detection/font/font_apple.m @@ -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); diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 85d951724..c63abaf5f 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -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 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; } diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 348a1ad33..31b7ab9e3 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -9,11 +9,22 @@ extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID display) __attribute__((weak_import)); +#ifndef MAC_OS_X_VERSION_10_15 +#import +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; diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index dbb55539e..d08aed435 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -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); diff --git a/src/detection/physicaldisk/physicaldisk_apple.c b/src/detection/physicaldisk/physicaldisk_apple.c index 8f4a11420..b60e466d3 100644 --- a/src/detection/physicaldisk/physicaldisk_apple.c +++ b/src/detection/physicaldisk/physicaldisk_apple.c @@ -7,17 +7,22 @@ #include #include #include -#include +#ifdef MAC_OS_X_VERSION_10_15 + #include +#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 } } diff --git a/src/detection/terminalshell/terminalshell_linux.c b/src/detection/terminalshell/terminalshell_linux.c index fbb90b207..77fd23c2a 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -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) { diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 64d90ccb2..8fdb40637 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -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*/: From 4f1cb779ab2d963689d975d495679b406c6cd2fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 11:12:06 +0800 Subject: [PATCH 45/65] OS (Linux): fix `BUILD_ID` not parsed --- src/detection/os/os_linux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/os/os_linux.c b/src/detection/os/os_linux.c index cd4844574..a4ea2f5cf 100644 --- a/src/detection/os/os_linux.c +++ b/src/detection/os/os_linux.c @@ -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}, From 1d95f9b22468a5b58a892f92c25c5e88965ba93c Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 19 May 2024 21:46:34 +0800 Subject: [PATCH 46/65] CMakeLists: unbreak build with GCC on macOS (#941) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bbb3ebc1..9bc94c94c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() From 27aa5c03439c59b8a37ab656b0e52aee4b146fe2 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 19 May 2024 21:51:46 +0800 Subject: [PATCH 47/65] opencl.c: unbreak build on macOS with no OpenCL support (#940) Fixes: https://github.com/fastfetch-cli/fastfetch/issues/939 --- src/detection/opencl/opencl.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 957c1c1dc..f3339bee8 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -1,6 +1,13 @@ #include "detection/opencl/opencl.h" -#if defined(FF_HAVE_OPENCL) || defined(__APPLE__) +#ifdef __APPLE__ +#include +#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; From 09ffd32144deed4a2b1b8cf4c0a9f1f5e631d418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 18:40:32 +0800 Subject: [PATCH 48/65] GPU (Linux): improve Intel GPU detection code --- src/detection/gpu/gpu_linux.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 1d0c612da..0b88d9991 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -100,24 +100,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) From e9b535d2776ffed04b069283e6846744ba6a8b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 19:34:48 +0800 Subject: [PATCH 49/65] GPU (Linux): improve perf --- src/detection/gpu/gpu_linux.c | 55 +++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 0b88d9991..03602bf5f 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -15,7 +15,7 @@ #include -static void pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) +static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) { ffStrbufAppendS(pciDir, "/driver"); char pathBuf[PATH_MAX]; @@ -35,8 +35,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) @@ -145,9 +148,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* drmPath) { - 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) @@ -157,15 +160,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 (drmPath) + { + 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) @@ -185,8 +196,8 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf 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); @@ -201,7 +212,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf #endif } } - ffStrbufSubstrBefore(drmDir, drmDirPathLength); + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); } if (gpu->name.length == 0) @@ -215,18 +226,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); + 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) { @@ -313,7 +324,7 @@ 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); @@ -358,7 +369,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); } From 3571d9277d9ae4754e9d1ac6c3966974ffdfff5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 19:41:23 +0800 Subject: [PATCH 50/65] CPU (Linux): take `--cpu-freq-ndigits` into account in `--cpu-format` --- src/modules/cpu/cpu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 16692c508..b32cd7f8f 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -79,11 +79,15 @@ void ffPrintCPU(FFCPUOptions* options) 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); + ffStrbufAppendF(&coreTypes, "%s%u", i == 0 ? "" : "+", cpu.coreTypes[i].count); } else ffStrbufAppendF(&coreTypes, "%u", cpu.coresOnline); + char freqBase[32], freqMax[32]; + snprintf(freqBase, sizeof(freqBase), "%.*f", options->freqNdigits, cpu.frequencyBase); + snprintf(freqMax, sizeof(freqMax), "%.*f", options->freqNdigits, cpu.frequencyMax); + 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[]){ @@ -92,8 +96,8 @@ 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_STRING, freqBase}, + {FF_FORMAT_ARG_TYPE_STRING, freqMax}, {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}, {FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes}, })); From 1b4fc3833043985ac815025e0848aaddb75ba236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 20:01:32 +0800 Subject: [PATCH 51/65] GPU (Linux): detect drm driver version --- src/detection/gpu/gpu_linux.c | 59 ++++++++++++++++++++++++++++++----- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 03602bf5f..f55ff6d07 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -15,8 +15,51 @@ #include -static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) +#ifdef FF_HAVE_DRM +#include "common/library.h" +#include "util/mallocHelper.h" + +#include +#include + +static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) { + FF_LIBRARY_LOAD(libdrm, &instance.config.library.libdrm, "dlopen(libdrm)" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetVersion); + + 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"; + + FF_AUTO_FREE drmVersionPtr version = ffdrmGetVersion(fd); + ffStrbufSetNS(&gpu->driver, (uint32_t) version->name_len, version->name); + 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, const char* drmKey) +{ + #ifdef FF_HAVE_DRM + 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)); @@ -148,7 +191,7 @@ static bool loadPciIds(FFstrbuf* pciids) return false; } -static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmPath) +static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) { const uint32_t drmDirPathLength = deviceDir->length; uint32_t vendorId, deviceId, subVendorId, subDeviceId; @@ -161,7 +204,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf char pciPath[PATH_MAX]; const char* pPciPath = NULL; - if (drmPath) + if (drmKey) { ssize_t pathLength = readlink(deviceDir->chars, pciPath, sizeof(pciPath) - 1); if (pathLength <= 0) @@ -194,6 +237,8 @@ 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(deviceDir, "/revision"); @@ -226,7 +271,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } - pciDetectDriver(gpu, deviceDir, buffer); + pciDetectDriver(gpu, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) @@ -274,7 +319,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?"; @@ -292,7 +337,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F 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); return NULL; } @@ -327,7 +372,7 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) 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); From 81485baadbaba2db248fbaa5df3072f5eed23baa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 18:23:18 +0800 Subject: [PATCH 52/65] CPU: better compatibility for Intel CPUs --- src/detection/cpu/cpu.h | 2 +- src/detection/cpu/cpu_bsd.c | 9 ++++----- src/detection/cpu/cpu_linux.c | 17 ++++++++--------- src/detection/cpu/cpu_windows.c | 16 +++++++--------- 4 files changed, 20 insertions(+), 24 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 982310cdb..2c69487bb 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -23,7 +23,7 @@ typedef struct FFCPUResult double frequencyMax; // GHz double frequencyMin; // GHz - FFCPUCore coreTypes[8]; // number of P cores, E cores, etc. + FFCPUCore coreTypes[16]; // number of P cores, E cores, etc. double temperature; } FFCPUResult; diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 2310ac432..80f767ca8 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -56,12 +56,11 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (!(cpu->frequencyMin <= fmin)) cpu->frequencyMin = fmin; // Counting for NaN if (!(cpu->frequencyMax >= fmax)) cpu->frequencyMax = fmax; - if (cpu->coreTypes[ifreq].freq != fmax) - { - if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) - ++ifreq; + 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++; } } diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index fdcd2e3e3..6034bd5de 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -136,7 +136,6 @@ static bool detectFrequency(FFCPUResult* cpu) FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); uint32_t baseLen = path.length; - uint32_t ifreq = 0; struct dirent* entry; while ((entry = readdir(dir)) != NULL) { @@ -158,14 +157,6 @@ static bool detectFrequency(FFCPUResult* cpu) cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax; else cpu->frequencyMax = fmax; - - if (cpu->coreTypes[ifreq].freq != fmax) - { - if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) - ++ifreq; - cpu->coreTypes[ifreq].freq = fmax; - } - cpu->coreTypes[ifreq].count += getNumCores(&path, &buffer); } uint32_t fmin = getFrequency(&path, "/cpuinfo_min_freq", "/scaling_min_freq", &buffer); if (fmin > 0) @@ -175,6 +166,14 @@ static bool detectFrequency(FFCPUResult* cpu) 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); } } diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 56cd5c839..9e27c7eba 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -166,16 +166,14 @@ static const char* detectCoreTypes(FFCPUResult* cpu) if (!NT_SUCCESS(NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, (ULONG) sizeof(PROCESSOR_POWER_INFORMATION) * cpu->coresLogical))) return "NtPowerInformation(ProcessorInformation, NULL, 0, pinfo, size) failed"; - uint32_t ifreq = 0; - for (uint32_t i = 0; i < cpu->coresLogical && pinfo[i].MhzLimit; ++i) + for (uint32_t icore = 0; icore < cpu->coresLogical && pinfo[icore].MhzLimit; ++icore) { - if (cpu->coreTypes[ifreq].freq != pinfo[i].MhzLimit) - { - if (cpu->coreTypes[ifreq].count && ifreq < sizeof(cpu->coreTypes) / sizeof(cpu->coreTypes[0])) - ++ifreq; - cpu->coreTypes[ifreq].freq = pinfo[i].MhzLimit; - } - cpu->coreTypes[ifreq].count++; + 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) From aba211221b252ee1bedc8523a5c512f003015327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 19 May 2024 23:07:02 +0800 Subject: [PATCH 53/65] Doc: update README [ci skip] --- .github/ISSUE_TEMPLATE/bug_report.md | 7 ++----- README.md | 7 +++++++ 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index be682e7b0..f955b1113 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -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. + # 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 - - * 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? diff --git a/README.md b/README.md index 0bde8cf53..814084c89 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,13 @@ See `fastfetch -h format` for basic usage. For module specific formattion, see ` 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: From 1619f0ab6c2fa4d4287a83b166dce6d8623c2534 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 20 May 2024 11:00:51 +0800 Subject: [PATCH 54/65] GPU (Linux): fix memory leaks --- src/detection/gpu/gpu_linux.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index f55ff6d07..11c35ecf9 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -26,13 +26,14 @@ static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* { FF_LIBRARY_LOAD(libdrm, &instance.config.library.libdrm, "dlopen(libdrm)" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetVersion); + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeVersion); 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"; - FF_AUTO_FREE drmVersionPtr version = ffdrmGetVersion(fd); + drmVersionPtr version = ffdrmGetVersion(fd); ffStrbufSetNS(&gpu->driver, (uint32_t) version->name_len, version->name); 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); @@ -46,6 +47,7 @@ static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* ffStrbufAppend(&gpu->driver, buffer); } } + ffdrmFreeVersion(version); return NULL; } #endif From c2eaea3665d57aa99264c0963da2e41c8db13651 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 20 May 2024 15:31:18 +0800 Subject: [PATCH 55/65] Logo (Builtin): fix KDE neon Fix #948 --- src/logo/builtin.c | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/logo/builtin.c b/src/logo/builtin.c index ba8403de6..bcc2549bb 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -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"}, @@ -2132,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 { From 10ca77610e8999369ca1fa4bdcbd9ac9799c1680 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 20 May 2024 15:32:13 +0800 Subject: [PATCH 56/65] GPU (Linux): detect GPU core count and freq for asahi linux --- src/detection/gpu/gpu_linux.c | 67 ++++++++++++++++++++++++++--------- src/modules/gpu/gpu.c | 2 ++ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 11c35ecf9..bc58f6c34 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -15,28 +15,44 @@ #include -#ifdef FF_HAVE_DRM -#include "common/library.h" -#include "util/mallocHelper.h" +#if __has_include() + #include + #define FF_HAVE_DRM_H 1 +#elif __has_include() + #include + #define FF_HAVE_DRM_H 1 +#endif -#include -#include +#if FF_HAVE_DRM_H + #include + #include + #if __aarch64__ && __has_include() + #include + #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) { - FF_LIBRARY_LOAD(libdrm, &instance.config.library.libdrm, "dlopen(libdrm)" FF_LIBRARY_EXTENSION " failed", "libdrm" FF_LIBRARY_EXTENSION, 2) - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetVersion); - FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmFreeVersion); - 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"; - drmVersionPtr version = ffdrmGetVersion(fd); - ffStrbufSetNS(&gpu->driver, (uint32_t) version->name_len, version->name); - 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); + 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"); @@ -47,14 +63,13 @@ static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* ffStrbufAppend(&gpu->driver, buffer); } } - ffdrmFreeVersion(version); return NULL; } #endif static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) { - #ifdef FF_HAVE_DRM + #if __has_include() if (drmKey) { drmDetectDriver(gpu, pciDir, buffer, drmKey); @@ -332,7 +347,7 @@ 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; @@ -341,6 +356,26 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F pciDetectDriver(gpu, drmDir, buffer, drmKey); + #if FF_HAVE_ASAHI_DRM_H + ffStrbufSetS(buffer, "/dev/dri/"); + ffStrbufAppendS(buffer, drmKey); + FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY); + if (fd >= 0) + { + struct drm_asahi_params_global paramsGlobal = {}; + if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params){ + .param_group = DRM_ASAHI_GET_PARAMS, + .pointer = (uint64_t) ¶msGlobal, + .size = sizeof(paramsGlobal), + }) >= 0) + { + gpu->coreCount = (int) paramsGlobal.num_cores_total_active; + gpu->frequency = paramsGlobal.max_frequency_khz / 1e6; + gpu->deviceId = paramsGlobal.chip_id; + } + } + #endif + return NULL; } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 47d9fa91e..3cb55a04c 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -127,6 +127,7 @@ void ffPrintGPU(FFGPUOptions* options) ffStrbufDestroy(&gpu->vendor); ffStrbufDestroy(&gpu->name); ffStrbufDestroy(&gpu->driver); + ffStrbufDestroy(&gpu->platformApi); } } @@ -327,6 +328,7 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ ffStrbufDestroy(&gpu->vendor); ffStrbufDestroy(&gpu->name); ffStrbufDestroy(&gpu->driver); + ffStrbufDestroy(&gpu->platformApi); } } From a8b734c8779be6affa9a341cbee58670a3dbcef9 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 20 May 2024 16:45:23 +0800 Subject: [PATCH 57/65] GPU: change option `--gpu-force-vulkan` to `--gpu-detection-method` --- completions/bash | 2 +- doc/json_schema.json | 14 +++++++--- src/data/help.json | 15 +++++++---- src/detection/gpu/gpu.c | 50 ++++++++++++++++++----------------- src/detection/gpu/gpu_linux.c | 18 +++++++------ src/fastfetch.c | 3 +++ src/modules/gpu/gpu.c | 47 +++++++++++++++++++++++++++----- src/modules/gpu/option.h | 11 +++++++- 8 files changed, 110 insertions(+), 50 deletions(-) diff --git a/completions/bash b/completions/bash index d3d6964c7..9ae14e00d 100644 --- a/completions/bash +++ b/completions/bash @@ -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" ) diff --git a/doc/json_schema.json b/doc/json_schema.json index 91ae40437..51b3301d8 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -1455,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", diff --git a/src/data/help.json b/src/data/help.json index 7e3631e35..3baa6b00a 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -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", "arg": { - "type": "bool", + "type": "enum", "optional": true, - "default": false + "enum": { + "auto": "DRM (Linux only) -> PCI (Linux, FreeBSD and other platform specific methods) -> Vulkan -> OpenGL", + "pci": "PCI -> Vulkan -> OpenGL", + "vulkan": "Vulkan -> OpenGL", + "opengl": "OpenGL" + }, + "default": "auto" } }, { diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index 4f70d3452..b75ac7679 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -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"; } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index bc58f6c34..9372882b3 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -460,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); } diff --git a/src/fastfetch.c b/src/fastfetch.c index 722c61462..cfe2d6185 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -234,10 +234,13 @@ static bool printSpecificCommandHelp(const char* command) } } + yyjson_doc_free(doc); return true; } } } + + yyjson_doc_free(doc); return false; } diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 3cb55a04c..5a9f4b4f3 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -144,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 = 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; } @@ -191,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; } @@ -230,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); @@ -366,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 }; diff --git a/src/modules/gpu/option.h b/src/modules/gpu/option.h index a68b8ad3a..405b7b11e 100644 --- a/src/modules/gpu/option.h +++ b/src/modules/gpu/option.h @@ -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; From 264b6794f3d10a9bd0f021d6ae149b47ee7ae9fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 18:33:47 +0800 Subject: [PATCH 58/65] CPU (Linux): detect bios limited frequency and print it by default To match neofetch's behavior Fix #947 --- src/detection/cpu/cpu.h | 2 +- src/detection/cpu/cpu_linux.c | 11 ++++++++++- src/modules/cpu/cpu.c | 27 ++++++++++++++++++++++----- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 2c69487bb..fc9b7e080 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -22,12 +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); diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 6034bd5de..c4c040bb2 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -150,6 +150,14 @@ static bool detectFrequency(FFCPUResult* cpu) else cpu->frequencyBase = fbase; } + 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) { @@ -167,7 +175,7 @@ static bool detectFrequency(FFCPUResult* cpu) cpu->frequencyMin = fmin; } - uint32_t freq = fbase <= 0 ? fmax : fbase; // seems base frequencies are more stable + 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; @@ -180,6 +188,7 @@ static bool detectFrequency(FFCPUResult* cpu) cpu->frequencyBase /= 1e6; cpu->frequencyMax /= 1e6; cpu->frequencyMin /= 1e6; + cpu->frequencyBiosLimit /= 1e6; return true; } diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index b32cd7f8f..5ec868c8c 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -6,7 +6,7 @@ #include "modules/cpu/cpu.h" #include "util/stringUtils.h" -#define FF_CPU_NUM_FORMAT_ARGS 9 +#define FF_CPU_NUM_FORMAT_ARGS 10 static int sortCores(const FFCPUCore* a, const FFCPUCore* b) { @@ -20,6 +20,7 @@ void ffPrintCPU(FFCPUOptions* options) .frequencyMin = 0.0/0.0, .frequencyMax = 0.0/0.0, .frequencyBase = 0.0/0.0, + .frequencyBiosLimit = 0.0/0.0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate() }; @@ -55,7 +56,9 @@ void ffPrintCPU(FFCPUOptions* options) if(cpu.coresOnline > 1) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); - double freq = cpu.frequencyMax; + double freq = cpu.frequencyBiosLimit; + if(freq <= 0.0000001) + freq = cpu.frequencyMax; if(freq <= 0.0000001) freq = cpu.frequencyBase; if(freq > 0.0000001) @@ -84,9 +87,19 @@ void ffPrintCPU(FFCPUOptions* options) else ffStrbufAppendF(&coreTypes, "%u", cpu.coresOnline); - char freqBase[32], freqMax[32]; - snprintf(freqBase, sizeof(freqBase), "%.*f", options->freqNdigits, cpu.frequencyBase); - snprintf(freqMax, sizeof(freqMax), "%.*f", options->freqNdigits, cpu.frequencyMax); + 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); @@ -100,6 +113,7 @@ void ffPrintCPU(FFCPUOptions* options) {FF_FORMAT_ARG_TYPE_STRING, freqMax}, {FF_FORMAT_ARG_TYPE_STRBUF, &tempStr}, {FF_FORMAT_ARG_TYPE_STRBUF, &coreTypes}, + {FF_FORMAT_ARG_TYPE_STRING, freqBioslimit}, })); } } @@ -173,6 +187,7 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ .frequencyMin = 0.0/0.0, .frequencyMax = 0.0/0.0, .frequencyBase = 0.0/0.0, + .frequencyBiosLimit = 0.0/0.0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate() }; @@ -202,6 +217,7 @@ 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++) @@ -230,6 +246,7 @@ void ffPrintCPUHelpFormat(void) "Max frequency", "Temperature (formatted)", "Logical core count grouped by frequency", + "Bios limited frequency", })); } From bb10e1c9a3b48e9f74d59658defc742099210703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 19:04:57 +0800 Subject: [PATCH 59/65] Doc: update help message of `--gpu-detection-method` --- src/data/help.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/data/help.json b/src/data/help.json index 3baa6b00a..74dde8d45 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1199,14 +1199,14 @@ { "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": "enum", - "optional": true, "enum": { - "auto": "DRM (Linux only) -> PCI (Linux, FreeBSD and other platform specific methods) -> Vulkan -> OpenGL", - "pci": "PCI -> Vulkan -> OpenGL", - "vulkan": "Vulkan -> OpenGL", - "opengl": "OpenGL" + "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" } From d9f1db10aab7f2ef9eb2eeebfde1d6a934450d45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 19:05:38 +0800 Subject: [PATCH 60/65] Completions (Fish): disable enum value suggestion --- completions/fish | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/completions/fish b/completions/fish index a078a795a..a1713e729 100755 --- a/completions/fish +++ b/completions/fish @@ -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': From 714b88c6389d1529bc7c7d45a615e47f63584b3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 19:14:32 +0800 Subject: [PATCH 61/65] Packages (Linux): try fixing nix-user detection Fix #937 --- src/detection/packages/packages_linux.c | 34 ++++++++++++------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 73920097f..5933c87c2 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -510,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"); } From 7af9cab688626f96ea0ad9c776397d99e39462ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 19:37:14 +0800 Subject: [PATCH 62/65] CI: try fixing Win32 build --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 287db4ea3..01ff21b4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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 From 188b6aba103f94811afaba8b724475837a3c69e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 20:39:54 +0800 Subject: [PATCH 63/65] Release: v2.13.0 --- CHANGELOG.md | 37 +++++++++++++++++++++++++++++++++++++ CMakeLists.txt | 2 +- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1869906db..9daf30a80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +# 2.13.0 + +Changes: +* Option `--gpu-force-vulkan ` has been changed to `--gpu-detection-method ` + * 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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bc94c94c..e3c528cc1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.12.0 + VERSION 2.13.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From 302716fa61216ca2a1d02a4bf70c128e07098625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 20:43:24 +0800 Subject: [PATCH 64/65] GPU: silence compiler warnings --- src/modules/gpu/gpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 5a9f4b4f3..b687b5a46 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -146,7 +146,7 @@ bool ffParseGPUCommandOptions(FFGPUOptions* options, const char* key, const char if (ffStrEqualsIgnCase(subKey, "detection-method")) { - options->detectionMethod = ffOptionParseEnum(key, value, (FFKeyValuePair[]) { + 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 }, From 8b43e331e3b5e2db1655dbb0e14606ea6921bfac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 20 May 2024 21:07:28 +0800 Subject: [PATCH 65/65] GPU (Linux): silence compiler warnings --- src/detection/gpu/gpu_linux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 9372882b3..9387ce4ef 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -67,9 +67,9 @@ static const char* drmDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* } #endif -static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) +static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) { - #if __has_include() + #if FF_HAVE_DRM_H if (drmKey) { drmDetectDriver(gpu, pciDir, buffer, drmKey);