From 9332f42889f4d5430edbc873b2782fcb463126a7 Mon Sep 17 00:00:00 2001 From: michela feng <5936271+aiwantaozi@users.noreply.github.com> Date: Thu, 19 Sep 2024 15:22:09 +0800 Subject: [PATCH 01/65] GPU: detect GPU index (#1267) --- src/detection/gpu/gpu.c | 1 + src/detection/gpu/gpu.h | 2 ++ src/detection/gpu/gpu_apple.m | 1 + src/detection/gpu/gpu_bsd.c | 2 ++ src/detection/gpu/gpu_driver_specific.h | 1 + src/detection/gpu/gpu_linux.c | 2 ++ src/detection/gpu/gpu_mthreads.c | 7 +++++++ src/detection/gpu/gpu_nvidia.c | 10 ++++++++++ src/detection/gpu/gpu_sunos.c | 1 + src/detection/gpu/gpu_windows.c | 4 +++- src/detection/gpu/gpu_wsl.cpp | 4 +++- src/detection/gpu/nvml.h | 2 ++ src/detection/opencl/opencl.c | 1 + src/detection/vulkan/vulkan.c | 1 + src/modules/gpu/gpu.c | 9 +++++++++ 15 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu.c b/src/detection/gpu/gpu.c index d1831f92a..a863760cd 100644 --- a/src/detection/gpu/gpu.c +++ b/src/detection/gpu/gpu.c @@ -55,6 +55,7 @@ const char* detectByOpenGL(FFlist* gpus) ffStrbufInitMove(&gpu->name, &result.renderer); ffStrbufInitMove(&gpu->driver, &result.vendor); ffStrbufInitF(&gpu->platformApi, "OpenGL %s", result.version.chars); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index a914d5c2d..7a269f5be 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,6 +7,7 @@ #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) #define FF_GPU_FREQUENCY_UNSET 0 #define FF_GPU_CORE_USAGE_UNSET (0/0.0) +#define FF_GPU_INDEX_UNSET ((uint8_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -27,6 +28,7 @@ typedef struct FFGPUMemory typedef struct FFGPUResult { + uint8_t index; FFGPUType type; FFstrbuf vendor; FFstrbuf name; diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index e5b6bebf6..709acf6fb 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -43,6 +43,7 @@ const char* ffGpuDetectMetal(FFlist* gpus) ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->index = (uint8_t)device.locationNumber; #endif } return NULL; diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 6d75ed9c1..6d07dc029 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -56,6 +56,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffStrbufInit(&gpu->name); ffStrbufInitS(&gpu->driver, pc->pd_name); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; @@ -90,6 +91,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .func = pc->pc_sel.pc_func, }, }, (FFGpuDriverResult) { + .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index 945b92cff..a163b9810 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -37,6 +37,7 @@ typedef struct FFGpuDriverCondition // detect x if not NULL typedef struct FFGpuDriverResult { + uint8_t* index; double* temp; FFGPUMemory* memory; uint32_t* coreCount; diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index cb038989e..7f8afd795 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -295,6 +295,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; @@ -366,6 +367,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .func = pciFunc, }, }, (FFGpuDriverResult) { + .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index ac0ffa07b..39cd955fc 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -134,6 +134,13 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive } } + if (result.index) + { + unsigned int value; + if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS) + *result.index = (uint8_t)value; + } + if (result.temp) { MtmlGpu *gpu = NULL; diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index fdd88f6ce..9738c8566 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -14,6 +14,7 @@ struct FFNvmlData { FF_LIBRARY_SYMBOL(nvmlDeviceGetMaxClockInfo) FF_LIBRARY_SYMBOL(nvmlDeviceGetUtilizationRates) FF_LIBRARY_SYMBOL(nvmlDeviceGetBrand) + FF_LIBRARY_SYMBOL(nvmlDeviceGetIndex) FF_LIBRARY_SYMBOL(nvmlDeviceGetName) bool inited; @@ -39,6 +40,7 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetMaxClockInfo) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetUtilizationRates) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetBrand) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetIndex) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(libnvml, nvmlData, nvmlDeviceGetName) if (ffnvmlInit_v2() != NVML_SUCCESS) @@ -105,6 +107,14 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR } } + if (result.index) + { + unsigned int value; + if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS) + *result.index = (uint8_t)value; + } + + if (result.temp) { uint32_t value; diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 442d87ce8..459e377b3 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -57,6 +57,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 6ad1cd2e8..d82929c29 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -38,6 +38,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufInit(&gpu->name); ffStrbufInit(&gpu->driver); ffStrbufInitStatic(&gpu->platformApi, "SetupAPI"); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; @@ -157,7 +158,8 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* }, .luid = gpu->deviceId, }, - (FFGpuDriverResult) { + (FFGpuDriverResult){ + .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, diff --git a/src/detection/gpu/gpu_wsl.cpp b/src/detection/gpu/gpu_wsl.cpp index ae144aca9..5448bb6b9 100644 --- a/src/detection/gpu/gpu_wsl.cpp +++ b/src/detection/gpu/gpu_wsl.cpp @@ -70,6 +70,7 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF FFGPUResult* gpu = (FFGPUResult*) ffListAdd(gpus); ffStrbufInitS(&gpu->name, desc); + gpu->index = FF_GPU_INDEX_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; @@ -117,7 +118,8 @@ const char* ffGPUDetectByDirectX(FF_MAYBE_UNUSED const FFGPUOptions* options, FF .revId = hardwareId.revision, }, }; - ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult) { + ffDetectNvidiaGpuInfo(&cond, (FFGpuDriverResult){ + .index = &gpu->index, .temp = options->temp ? &gpu->temperature : NULL, .memory = options->driverSpecific ? &gpu->dedicated : NULL, .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, diff --git a/src/detection/gpu/nvml.h b/src/detection/gpu/nvml.h index fd10d651f..693f9bff8 100644 --- a/src/detection/gpu/nvml.h +++ b/src/detection/gpu/nvml.h @@ -132,5 +132,7 @@ extern nvmlReturn_t nvmlDeviceGetMaxClockInfo(nvmlDevice_t device, nvmlClockType extern nvmlReturn_t nvmlDeviceGetBrand(nvmlDevice_t device, nvmlBrandType_t* type); // Retrieves the current utilization rates for the device extern nvmlReturn_t nvmlDeviceGetUtilizationRates(nvmlDevice_t device, nvmlUtilization_t *utilization); +// Retrieves the globally unique immutable UUID associated with this device, as a 5 part hexadecimal string, that augments the immutable, board serial identifier. +extern nvmlReturn_t nvmlDeviceGetIndex(nvmlDevice_t device, unsigned int *index); // Retrieves the name of this device. extern nvmlReturn_t nvmlDeviceGetName(nvmlDevice_t device, char *name, unsigned int length); diff --git a/src/detection/opencl/opencl.c b/src/detection/opencl/opencl.c index 9254816a1..cb5176257 100644 --- a/src/detection/opencl/opencl.c +++ b/src/detection/opencl/opencl.c @@ -75,6 +75,7 @@ static const char* openCLHandleData(OpenCLData* data, FFOpenCLResult* result) ffStrbufInit(&gpu->vendor); ffStrbufInit(&gpu->driver); ffStrbufInit(&gpu->platformApi); + gpu->index = FF_GPU_INDEX_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; diff --git a/src/detection/vulkan/vulkan.c b/src/detection/vulkan/vulkan.c index 1d49ec584..eb4c05ac8 100644 --- a/src/detection/vulkan/vulkan.c +++ b/src/detection/vulkan/vulkan.c @@ -234,6 +234,7 @@ static const char* detectVulkan(FFVulkanResult* result) } //No way to detect those using vulkan + gpu->index = FF_GPU_INDEX_UNSET; gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->temperature = FF_GPU_TEMP_UNSET; gpu->frequency = FF_GPU_FREQUENCY_UNSET; diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index bdc2e890d..32c719eb2 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -322,6 +322,15 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ FF_LIST_FOR_EACH(FFGPUResult, gpu, gpus) { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); + + if (gpu->index != FF_GPU_INDEX_UNSET){ + yyjson_mut_obj_add_uint(doc, obj, "index", (uint64_t)gpu->index); + } + else + { + yyjson_mut_obj_add_null(doc, obj, "index"); + } + if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount); else From 0bcbae90e9f4edaf1b79e815dcef3f731f9c7f46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 19 Sep 2024 15:38:43 +0800 Subject: [PATCH 02/65] GPU: clean up GPU index detection code --- src/detection/gpu/gpu.h | 2 +- src/detection/gpu/gpu_amd.c | 3 +++ src/detection/gpu/gpu_apple.m | 2 +- src/detection/gpu/gpu_driver_specific.h | 2 +- src/detection/gpu/gpu_mthreads.c | 2 +- src/detection/gpu/gpu_nvidia.c | 4 ++-- src/modules/gpu/gpu.c | 11 +++++------ 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 7a269f5be..95a7aab41 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -28,7 +28,7 @@ typedef struct FFGPUMemory typedef struct FFGPUResult { - uint8_t index; + uint32_t index; FFGPUType type; FFstrbuf vendor; FFstrbuf name; diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 1510019ea..2b55c80d2 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -65,5 +65,8 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu if (result.type) *result.type = device->isAPU ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + if (result.index) + *result.type = (uint32_t) device->adlAdapterIndex; + return NULL; } diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 709acf6fb..aead1c217 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -43,7 +43,7 @@ const char* ffGpuDetectMetal(FFlist* gpus) ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; - gpu->index = (uint8_t)device.locationNumber; + gpu->index = (uint32_t) device.locationNumber; #endif } return NULL; diff --git a/src/detection/gpu/gpu_driver_specific.h b/src/detection/gpu/gpu_driver_specific.h index a163b9810..989ef6093 100644 --- a/src/detection/gpu/gpu_driver_specific.h +++ b/src/detection/gpu/gpu_driver_specific.h @@ -37,7 +37,7 @@ typedef struct FFGpuDriverCondition // detect x if not NULL typedef struct FFGpuDriverResult { - uint8_t* index; + uint32_t* index; double* temp; FFGPUMemory* memory; uint32_t* coreCount; diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index 39cd955fc..7af21c58f 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -138,7 +138,7 @@ const char *ffDetectMthreadsGpuInfo(const FFGpuDriverCondition *cond, FFGpuDrive { unsigned int value; if (mtmlData.ffmtmlDeviceGetIndex(device, &value) == MTML_SUCCESS) - *result.index = (uint8_t)value; + *result.index = value; } if (result.temp) diff --git a/src/detection/gpu/gpu_nvidia.c b/src/detection/gpu/gpu_nvidia.c index 9738c8566..c2cc33d1d 100644 --- a/src/detection/gpu/gpu_nvidia.c +++ b/src/detection/gpu/gpu_nvidia.c @@ -111,9 +111,9 @@ const char* ffDetectNvidiaGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverR { unsigned int value; if (nvmlData.ffnvmlDeviceGetIndex(device, &value) == NVML_SUCCESS) - *result.index = (uint8_t)value; + *result.index = value; } - + if (result.temp) { diff --git a/src/modules/gpu/gpu.c b/src/modules/gpu/gpu.c index 32c719eb2..1d449d33a 100644 --- a/src/modules/gpu/gpu.c +++ b/src/modules/gpu/gpu.c @@ -10,7 +10,7 @@ #include -#define FF_GPU_NUM_FORMAT_ARGS 12 +#define FF_GPU_NUM_FORMAT_ARGS 13 static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResult* gpu) { @@ -103,6 +103,7 @@ static void printGPUResult(FFGPUOptions* options, uint8_t index, const FFGPUResu FF_FORMAT_ARG(sUsed, "shared-used"), FF_FORMAT_ARG(gpu->platformApi, "platform-api"), FF_FORMAT_ARG(frequency, "frequency"), + FF_FORMAT_ARG(index, "index"), })); } } @@ -323,13 +324,10 @@ void ffGenerateGPUJsonResult(FFGPUOptions* options, yyjson_mut_doc* doc, yyjson_ { yyjson_mut_val* obj = yyjson_mut_arr_add_obj(doc, arr); - if (gpu->index != FF_GPU_INDEX_UNSET){ - yyjson_mut_obj_add_uint(doc, obj, "index", (uint64_t)gpu->index); - } + if (gpu->index != FF_GPU_INDEX_UNSET) + yyjson_mut_obj_add_uint(doc, obj, "index", gpu->index); else - { yyjson_mut_obj_add_null(doc, obj, "index"); - } if (gpu->coreCount != FF_GPU_CORE_COUNT_UNSET) yyjson_mut_obj_add_int(doc, obj, "coreCount", gpu->coreCount); @@ -411,6 +409,7 @@ void ffPrintGPUHelpFormat(void) "GPU used shared memory - shared-used", "The platform API used when detecting the GPU - platform-api", "Current frequency in GHz - frequency", + "GPU vendor specific index - index", })); } From 006c00ab2c24c9c6ef9081eeb1dc13d5253aa8dc Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 20 Sep 2024 14:13:52 +0800 Subject: [PATCH 03/65] Packaging: update debian stuff [ci skip] --- debian/changelog | 6 ++++++ debian/files | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/debian/changelog b/debian/changelog index 647ba54c1..caa889c2f 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +fastfetch (2.25.0) jammy; urgency=medium + + * Update to 2.25.0 + + -- Carter Li Thu, 19 Sep 2024 10:28:38 +0800 + fastfetch (2.24.0) jammy; urgency=medium * Update to 2.24.0 diff --git a/debian/files b/debian/files index 1e5930ffc..fc11a7155 100644 --- a/debian/files +++ b/debian/files @@ -1 +1 @@ -fastfetch_2.24.0_source.buildinfo universe/utils optional +fastfetch_2.25.0_source.buildinfo universe/utils optional From db669c00a1acc2a2363463f22e6b667ab0c0cce0 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 20 Sep 2024 15:33:04 +0800 Subject: [PATCH 04/65] TerminalFont (Linux): fix font size detection of foot when fall back font is used Fix #1276 --- src/detection/terminalfont/terminalfont_linux.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/detection/terminalfont/terminalfont_linux.c b/src/detection/terminalfont/terminalfont_linux.c index 843648c57..baf383def 100644 --- a/src/detection/terminalfont/terminalfont_linux.c +++ b/src/detection/terminalfont/terminalfont_linux.c @@ -244,13 +244,19 @@ static void detectFootTerminal(FFTerminalFontResult* terminalFont) return; } uint32_t equal = ffStrbufNextIndexS(&font, colon, "size="); - font.chars[colon] = 0; + font.chars[colon] = '\0'; if (equal == font.length) { ffFontInitValues(&terminalFont->font, font.chars, "8"); return; } - ffFontInitValues(&terminalFont->font, font.chars, &font.chars[equal + strlen("size=")]); + uint32_t size = equal + strlen("size="); + uint32_t comma = ffStrbufNextIndexC(&font, size, ','); + if (comma < font.length) + font.chars[comma] = '\0'; + ffFontInitValues(&terminalFont->font, font.chars, &font.chars[size]); + if (comma < font.length) + ffFontInitValues(&terminalFont->fallback, &font.chars[comma + 1], NULL); } static void detectQTerminal(FFTerminalFontResult* terminalFont) From 1dba6d155b546d4b7439a9513607aa3668b185f7 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 20 Sep 2024 15:33:30 +0800 Subject: [PATCH 05/65] TerminalShell (Linux): improve performance of foot version detection --- src/detection/terminalshell/terminalshell.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index c44ecc32c..05cf9c4ca 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -365,6 +365,13 @@ FF_MAYBE_UNUSED static bool getTerminalVersionKonsole(FFstrbuf* exe, FFstrbuf* v FF_MAYBE_UNUSED static bool getTerminalVersionFoot(FFstrbuf* exe, FFstrbuf* version) { + uint32_t major = 0, minor = 0, patch = 0; + if (ffGetTerminalResponse("\e[>c", 3, "\e[>1;%2u%2u%2u;0c", &major, &minor, &patch) == NULL) + { + ffStrbufSetF(version, "%u.%u.%u", major, minor, patch); + return true; + } + if(!getExeVersionRaw(exe, version)) return false; //foot version: 1.13.1 -pgo +ime -graphemes -assertions From 85a31c7c6986ae66c9cc2aa48c895b592028b414 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 20 Sep 2024 16:30:00 +0800 Subject: [PATCH 06/65] TerminalShell (Linux): improve perf of yakuake version detection --- src/detection/terminalshell/terminalshell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalshell/terminalshell.c b/src/detection/terminalshell/terminalshell.c index 05cf9c4ca..4280f20df 100644 --- a/src/detection/terminalshell/terminalshell.c +++ b/src/detection/terminalshell/terminalshell.c @@ -671,7 +671,7 @@ bool fftsGetTerminalVersion(FFstrbuf* processName, FF_MAYBE_UNUSED FFstrbuf* exe return getTerminalVersionKonsole(exe, version); if(ffStrbufIgnCaseEqualS(processName, "yakuake")) - return getExeVersionGeneral(exe, version);//yakuake 22.12.3 + return getTerminalVersionKonsole(exe, version); // yakuake shares code with konsole if(ffStrbufIgnCaseEqualS(processName, "xfce4-terminal")) return getTerminalVersionXfce4Terminal(exe, version); From 866c7303e6c8df210c85e9fdd5efe3c875c69e9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 20 Sep 2024 20:25:59 +0800 Subject: [PATCH 07/65] Chore (Windows): use standard libc api --- src/detection/bootmgr/bootmgr_windows.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/bootmgr/bootmgr_windows.c b/src/detection/bootmgr/bootmgr_windows.c index af6199b80..19484a7ed 100644 --- a/src/detection/bootmgr/bootmgr_windows.c +++ b/src/detection/bootmgr/bootmgr_windows.c @@ -38,7 +38,7 @@ const char* ffDetectBootmgr(FFBootmgrResult* result) uint8_t buffer[2048]; wchar_t key[16]; - wsprintfW(key, L"Boot%04X", value); + swprintf(key, sizeof(key) / sizeof(*key), L"Boot%04X", value); uint32_t size = GetFirmwareEnvironmentVariableW(key, L"{" FF_EFI_GLOBAL_GUID L"}", buffer, sizeof(buffer)); if (size < sizeof(FFEfiLoadOption) || size == sizeof(buffer)) return "GetFirmwareEnvironmentVariableW(Boot####) failed"; From 005d660d77a4a217c0cc46167197ea80a762c9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 21 Sep 2024 23:04:45 +0800 Subject: [PATCH 08/65] Logo (Builtin): add FoxOS Fix #1281 --- src/logo/ascii/foxos.txt | 8 ++++++++ src/logo/builtin.c | 8 ++++++++ 2 files changed, 16 insertions(+) create mode 100644 src/logo/ascii/foxos.txt diff --git a/src/logo/ascii/foxos.txt b/src/logo/ascii/foxos.txt new file mode 100644 index 000000000..91f114bb0 --- /dev/null +++ b/src/logo/ascii/foxos.txt @@ -0,0 +1,8 @@ + ________ ________ ___ ___ ________ ________ +|\ _____\\ __ \ |\ \ / /|\ __ \|\ ____\ +\ \ \__/\ \ \|\ \ \ \ \/ / | \ \|\ \ \ \___|_ + \ \ __\\ \ \\\ \ \ \ / / \ \ \\\ \ \_____ \ + \ \ \_| \ \ \\\ \ / \/ \ \ \\\ \|____|\ \ + \ \__\ \ \_______\/ /\ \ \ \_______\____\_\ \ + \|__| \|_______/__/ /\ __\ \|_______|\_________\ + |__|/ \|__| \|_________| \ No newline at end of file diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 52f1a9166..1fd6d86be 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1666,6 +1666,14 @@ static const FFlogo F[] = { .colorKeys = FF_COLOR_FG_RED, .colorTitle = FF_COLOR_FG_WHITE, }, + // FoxOS + { + .names = {"FoxOS"}, + .lines = FASTFETCH_DATATEXT_LOGO_FOXOS, + .colors = { + FF_COLOR_FG_YELLOW, + }, + }, // FreeBSD { .names = {"Freebsd"}, From fc947468a9b63c7fc3f383d2e17f27a160553a2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Sep 2024 10:31:59 +0800 Subject: [PATCH 09/65] Terminal: ignore `sudo` and `su` Fix #1283 --- 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 da4e96dfd..0355e2563 100644 --- a/src/detection/terminalshell/terminalshell_linux.c +++ b/src/detection/terminalshell/terminalshell_linux.c @@ -83,6 +83,8 @@ static pid_t getTerminalInfo(FFTerminalResult* result, pid_t pid) { //Known shells if ( + ffStrbufEqualS(&result->processName, "sudo") || + ffStrbufEqualS(&result->processName, "su") || ffStrbufEqualS(&result->processName, "sh") || ffStrbufEqualS(&result->processName, "ash") || ffStrbufEqualS(&result->processName, "bash") || From 10868ed9515c39b0b176075a7d91c94bc1a5f99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Sep 2024 10:45:18 +0800 Subject: [PATCH 10/65] Doc: update README [ci skip] --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e82de5b39..83a880b0e 100644 --- a/README.md +++ b/README.md @@ -152,13 +152,13 @@ Fastfetch uses `format` to generate output. For example, to make the `GPU` modul "modules": [ { "type": "gpu", - "format": "{2}" // See `fastfetch -h gpu-format` for detail + "format": "{name}" // See `fastfetch -h gpu-format` for detail } ] } ``` -. . which is equivalent to `fastfetch -s gpu --gpu-format '{2}'` +. . which is equivalent to `fastfetch -s gpu --gpu-format '{name}'` See `fastfetch -h format` for information on basic usage. For module specific formattion, see `fastfetch -h -format` @@ -186,6 +186,10 @@ You can always use `fastfetch --pipe false` to force fastfetch running in colorf See [#1096](https://github.com/fastfetch-cli/fastfetch/issues/1096). +### Q: I use Debian / Ubuntu / Debian deserved distro. My GPU is detected as `XXXX Device XXXX (VGA compatible)`. Is it a bug? + +See [#1282](https://github.com/fastfetch-cli/fastfetch/issues/1282) + ### Q: I want feature A / B / C. Will fastfetch support it? Fastfetch is a system information tool. We only accept hardware or system level software feature requests. For most personal uses, I recommend using `Command` module to detect it yourself, which can be used to grab output from a custom shell script: From a77d97283460986542dca085c35cda2036688d38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Sep 2024 12:21:56 +0800 Subject: [PATCH 11/65] Packages (Linux): count flatpak runtime packages Fix #1085 --- src/detection/packages/packages_linux.c | 76 ++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index f3ca054f2..3aa0e2b12 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -467,6 +467,78 @@ static uint32_t getGuixPackages(FFstrbuf* baseDir, const char* dirname) return num_elements; } +static inline uint32_t getFlatpakRuntimePackagesArch(FFstrbuf* baseDir) +{ + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + num_elements += getNumElements(baseDir, entry->d_name, DT_DIR); + } + } + + return num_elements; +} + +static inline uint32_t getFlatpakRuntimePackages(FFstrbuf* baseDir) +{ + ffStrbufAppendS(baseDir, "runtime/"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir->chars); + if (dirp == NULL) + return 0; + + uint32_t runtimeDirLength = baseDir->length; + uint32_t num_elements = 0; + + struct dirent *entry; + while ((entry = readdir(dirp)) != NULL) + { + if(entry->d_type == DT_DIR && entry->d_name[0] != '.') + { + // `flatpak list` ignores `.Locale` and `.Debug` packages, and maybe others + const char* dot = strrchr(entry->d_name, '.'); + if (__builtin_expect(!dot, false)) continue; + dot++; + + if (ffStrEquals(dot, "Locale") || ffStrEquals(dot, "Debug")) + continue; + + ffStrbufAppendS(baseDir, entry->d_name); + ffStrbufAppendC(baseDir, '/'); + num_elements += getFlatpakRuntimePackagesArch(baseDir); + ffStrbufSubstrBefore(baseDir, runtimeDirLength); + } + } + + return num_elements; +} + +static uint32_t getFlatpakPackages(FFstrbuf* baseDir, const char* dirname) +{ + uint32_t num_elements = 0; + uint32_t baseDirLength = baseDir->length; + ffStrbufAppendS(baseDir, dirname); + ffStrbufAppendS(baseDir, "/flatpak/"); + uint32_t flatpakDirLength = baseDir->length; + + ffStrbufAppendS(baseDir, "app"); + num_elements += getNumElementsImpl(baseDir->chars, DT_DIR); + ffStrbufSubstrBefore(baseDir, flatpakDirLength); + + num_elements += getFlatpakRuntimePackages(baseDir); + + ffStrbufSubstrBefore(baseDir, baseDirLength); + + return num_elements; +} + static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) { if (!(options->disabled & FF_PACKAGES_FLAG_APK_BIT)) packageCounts->apk += getNumStrings(baseDir, "/lib/apk/db/installed", "C:Q", "apk"); @@ -474,7 +546,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, if (!(options->disabled & FF_PACKAGES_FLAG_LPKG_BIT)) packageCounts->lpkg += getNumStrings(baseDir, "/opt/Loc-OS-LPKG/installed-lpkg/Listinstalled-lpkg.list", "\n", "lpkg"); if (!(options->disabled & FF_PACKAGES_FLAG_EMERGE_BIT)) packageCounts->emerge += countFilesRecursive(baseDir, "/var/db/pkg", "SIZE"); if (!(options->disabled & FF_PACKAGES_FLAG_EOPKG_BIT)) packageCounts->eopkg += getNumElements(baseDir, "/var/lib/eopkg/package", DT_DIR); - if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getNumElements(baseDir, "/var/lib/flatpak/app", DT_DIR); + if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) packageCounts->flatpakSystem += getFlatpakPackages(baseDir, "/var/lib"); if (!(options->disabled & FF_PACKAGES_FLAG_NIX_BIT)) { packageCounts->nixDefault += getNixPackages(baseDir, "/nix/var/nix/profiles/default"); @@ -603,5 +675,5 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options) } if (!(options->disabled & FF_PACKAGES_FLAG_FLATPAK_BIT)) - result->flatpakUser = getNumElements(&baseDir, "/.local/share/flatpak/app", DT_DIR); + result->flatpakUser = getFlatpakPackages(&baseDir, "/.local/share"); } From c936d170b26dd5a93e96f2933d2b152e89841449 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Sep 2024 12:30:37 +0800 Subject: [PATCH 12/65] Packages (Linux): support pacstall --- src/detection/packages/packages.h | 1 + src/detection/packages/packages_linux.c | 1 + src/modules/packages/option.h | 1 + src/modules/packages/packages.c | 13 ++++++++++--- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/detection/packages/packages.h b/src/detection/packages/packages.h index 43e9a78b4..aef482d84 100644 --- a/src/detection/packages/packages.h +++ b/src/detection/packages/packages.h @@ -35,6 +35,7 @@ typedef struct FFPackagesResult uint32_t sorcery; uint32_t winget; uint32_t xbps; + uint32_t pacstall; uint32_t all; //Make sure this goes last diff --git a/src/detection/packages/packages_linux.c b/src/detection/packages/packages_linux.c index 3aa0e2b12..187b0bdf2 100644 --- a/src/detection/packages/packages_linux.c +++ b/src/detection/packages/packages_linux.c @@ -572,6 +572,7 @@ static void getPackageCounts(FFstrbuf* baseDir, FFPackagesResult* packageCounts, packageCounts->guixSystem += getGuixPackages(baseDir, "/run/current-system/profile"); } if (!(options->disabled & FF_PACKAGES_FLAG_LINGLONG_BIT)) packageCounts->linglong += getNumElements(baseDir, "/var/lib/linglong/repo/refs/heads/main", DT_DIR); + if (!(options->disabled & FF_PACKAGES_FLAG_PACSTALL_BIT)) packageCounts->pacstall += getNumElements(baseDir, "/var/lib/pacstall/metadata", DT_REG); } static void getPackageCountsRegular(FFstrbuf* baseDir, FFPackagesResult* packageCounts, FFPackagesOptions* options) diff --git a/src/modules/packages/option.h b/src/modules/packages/option.h index de28caa33..e3f3d54c7 100644 --- a/src/modules/packages/option.h +++ b/src/modules/packages/option.h @@ -32,6 +32,7 @@ typedef enum FFPackagesFlags FF_PACKAGES_FLAG_LPKGBUILD_BIT = 1 << 22, FF_PACKAGES_FLAG_GUIX_BIT = 1 << 23, FF_PACKAGES_FLAG_LINGLONG_BIT = 1 << 24, + FF_PACKAGES_FLAG_PACSTALL_BIT = 1 << 25, } FFPackagesFlags; typedef struct FFPackagesOptions diff --git a/src/modules/packages/packages.c b/src/modules/packages/packages.c index 3e2b09fc7..e33b18d49 100644 --- a/src/modules/packages/packages.c +++ b/src/modules/packages/packages.c @@ -4,7 +4,7 @@ #include "modules/packages/packages.h" #include "util/stringUtils.h" -#define FF_PACKAGES_NUM_FORMAT_ARGS 37 +#define FF_PACKAGES_NUM_FORMAT_ARGS 38 void ffPrintPackages(FFPackagesOptions* options) { @@ -72,6 +72,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_PRINT_PACKAGE_NAME(guixUser, "guix-user") FF_PRINT_PACKAGE_NAME(guixHome, "guix-home") FF_PRINT_PACKAGE(linglong) + FF_PRINT_PACKAGE(pacstall) putchar('\n'); } @@ -115,6 +116,7 @@ void ffPrintPackages(FFPackagesOptions* options) FF_FORMAT_ARG(counts.guixUser, "guix-user"), FF_FORMAT_ARG(counts.guixHome, "guix-home"), FF_FORMAT_ARG(counts.linglong, "linglong"), + FF_FORMAT_ARG(counts.pacstall, "pacstall"), FF_FORMAT_ARG(nixAll, "nix-all"), FF_FORMAT_ARG(flatpakAll, "flatpak-all"), FF_FORMAT_ARG(brewAll, "brew-all"), @@ -186,9 +188,10 @@ bool ffParsePackagesCommandOptions(FFPackagesOptions* options, const char* key, break; case 'P': if (false); FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) + FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PALUDIS) break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) @@ -295,9 +298,10 @@ void ffParsePackagesJsonObject(FFPackagesOptions* options, yyjson_val* module) break; case 'P': if (false); FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) + FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) - FF_TEST_PACKAGE_NAME(PALUDIS) break; case 'R': if (false); FF_TEST_PACKAGE_NAME(RPM) @@ -352,6 +356,7 @@ void ffGeneratePackagesJsonConfig(FFPackagesOptions* options, yyjson_mut_doc* do FF_TEST_PACKAGE_NAME(NIX) FF_TEST_PACKAGE_NAME(OPKG) FF_TEST_PACKAGE_NAME(PACMAN) + FF_TEST_PACKAGE_NAME(PACSTALL) FF_TEST_PACKAGE_NAME(PALUDIS) FF_TEST_PACKAGE_NAME(PKG) FF_TEST_PACKAGE_NAME(PKGTOOL) @@ -412,6 +417,7 @@ void ffGeneratePackagesJsonResult(FF_MAYBE_UNUSED FFPackagesOptions* options, yy FF_APPEND_PACKAGE_COUNT(guixUser) FF_APPEND_PACKAGE_COUNT(guixHome) FF_APPEND_PACKAGE_COUNT(linglong) + FF_APPEND_PACKAGE_COUNT(pacstall) yyjson_mut_obj_add_strbuf(doc, obj, "pacmanBranch", &counts.pacmanBranch); } @@ -451,6 +457,7 @@ void ffPrintPackagesHelpFormat(void) "Number of guix-user packages - guix-user", "Number of guix-home packages - guix-home", "Number of linglong packages - linglong", + "Number of pacstall packages - pacstall", "Total number of all nix packages - nix-all", "Total number of all flatpak app packages - flatpak-all", "Total number of all brew packages - brew-all", From bd2b002d1458510bdc07446b6e49591fa2258e99 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 19 Sep 2024 19:42:02 +0800 Subject: [PATCH 13/65] Display: always print inches in integer --- src/modules/display/display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/display/display.c b/src/modules/display/display.c index 4e3f67eb3..ff1c93528 100644 --- a/src/modules/display/display.c +++ b/src/modules/display/display.c @@ -100,7 +100,7 @@ void ffPrintDisplay(FFDisplayOptions* options) } FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - double inch = sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4; + uint32_t inch = (uint32_t) (sqrt(result->physicalWidth * result->physicalWidth + result->physicalHeight * result->physicalHeight) / 25.4 + 0.5); if(options->moduleArgs.outputFormat.length == 0) { @@ -121,8 +121,8 @@ void ffPrintDisplay(FFDisplayOptions* options) result->scaledHeight > 0 && result->scaledHeight != result->height) ffStrbufAppendF(&buffer, " (as %ix%i)", result->scaledWidth, result->scaledHeight); - if (inch > 0) - ffStrbufAppendF(&buffer, " in %i″", (uint32_t) (inch + 0.5)); + if (inch > 1) + ffStrbufAppendF(&buffer, " in %i″", inch); if(result->type != FF_DISPLAY_TYPE_UNKNOWN) ffStrbufAppendS(&buffer, result->type == FF_DISPLAY_TYPE_BUILTIN ? " [Built-in]" : " [External]"); From e0296b75f6324f43ca05bef20b2cb430ce934261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 22 Sep 2024 19:15:03 +0800 Subject: [PATCH 14/65] Doc: add donation info --- .github/FUNDING.yml | 1 - README.md | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 183ade642..000000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -github: [CarterLi, LinusDierheimer] diff --git a/README.md b/README.md index 83a880b0e..2d6e8e3d0 100644 --- a/README.md +++ b/README.md @@ -214,6 +214,13 @@ Otherwise, open a feature request in [GitHub Issues](https://github.com/fastfetc * For usage questions, please start a discussion in [GitHub Discussions](https://github.com/fastfetch-cli/fastfetch/discussions). * For possible bugs, please open an issue in [GitHub Issues](https://github.com/fastfetch-cli/fastfetch/issues). Be sure to fill the bug-report template carefully for developers to investigate. +## Donate + +If you find Fastfetch to be useful, please consider donating. + +* Current maintainer: [@CarterLi](https://paypal.me/zhangsongcui) +* Original author: [@LinusDierheimer](https://github.com/sponsors/LinusDierheimer) + ## Star History Give it a star to support us! From b3b6e5fec1ca845193366081ddda55331e7f99ca Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 23 Sep 2024 14:32:38 +0800 Subject: [PATCH 15/65] GPU (Linux): refactor; add amdgpu DRM connector --- src/detection/gpu/gpu.h | 4 +- src/detection/gpu/gpu_asahi.h | 91 ++++++++++++ src/detection/gpu/gpu_linux.c | 273 +++++++++++++++++++--------------- 3 files changed, 248 insertions(+), 120 deletions(-) create mode 100644 src/detection/gpu/gpu_asahi.h diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 95a7aab41..85a51c278 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -7,7 +7,7 @@ #define FF_GPU_VMEM_SIZE_UNSET ((uint64_t)-1) #define FF_GPU_FREQUENCY_UNSET 0 #define FF_GPU_CORE_USAGE_UNSET (0/0.0) -#define FF_GPU_INDEX_UNSET ((uint8_t)-1) +#define FF_GPU_INDEX_UNSET ((uint32_t)-1) extern const char* FF_GPU_VENDOR_NAME_APPLE; extern const char* FF_GPU_VENDOR_NAME_AMD; @@ -40,7 +40,7 @@ typedef struct FFGPUResult uint32_t frequency; // Maximum time clock frequency in MHz FFGPUMemory dedicated; FFGPUMemory shared; - uint64_t deviceId; // Used internally, may be uninitialized + uint64_t deviceId; } FFGPUResult; const char* ffDetectGPU(const FFGPUOptions* options, FFlist* result); diff --git a/src/detection/gpu/gpu_asahi.h b/src/detection/gpu/gpu_asahi.h new file mode 100644 index 000000000..b6cf9b65b --- /dev/null +++ b/src/detection/gpu/gpu_asahi.h @@ -0,0 +1,91 @@ +#if __aarch64__ && FF_HAVE_DRM + +#include +#include +#include + +#if __has_include() + +#include + +#else + +// https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h +/* SPDX-License-Identifier: MIT */ +/* Copyright (C) The Asahi Linux Contributors */ + +#define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011 + +#define DRM_ASAHI_GET_PARAMS 0x00 +#define DRM_ASAHI_MAX_CLUSTERS 32 +struct drm_asahi_params_global +{ + __u32 unstable_uabi_version; + __u32 pad0; + + __u64 feat_compat; + __u64 feat_incompat; + + __u32 gpu_generation; + __u32 gpu_variant; + __u32 gpu_revision; + __u32 chip_id; + + __u32 num_dies; + __u32 num_clusters_total; + __u32 num_cores_per_cluster; + __u32 num_frags_per_cluster; + __u32 num_gps_per_cluster; + __u32 num_cores_total_active; + __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; + + __u32 vm_page_size; + __u32 pad1; + __u64 vm_user_start; + __u64 vm_user_end; + __u64 vm_usc_start; + __u64 vm_usc_end; + __u64 vm_kernel_min_size; + + __u32 max_syncs_per_submission; + __u32 max_commands_per_submission; + __u32 max_commands_in_flight; + __u32 max_attachments; + + __u32 timer_frequency_hz; + __u32 min_frequency_khz; + __u32 max_frequency_khz; + __u32 max_power_mw; + + __u32 result_render_size; + __u32 result_compute_size; + + __u32 firmware_version[4]; +}; + +struct drm_asahi_get_params +{ + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @param: Parameter group to fetch (MBZ) */ + __u32 param_group; + + /** @pad: MBZ */ + __u32 pad; + + /** @value: User pointer to write parameter struct */ + __u64 pointer; + + /** @value: Size of user buffer, max size supported on return */ + __u64 size; +}; + +enum +{ + DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), +}; + +#endif // __has_include + +#endif // FF_HAVE_DRM diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 7f8afd795..14bdaca97 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -4,97 +4,24 @@ #include "detection/cpu/cpu.h" #include "detection/gpu/gpu_driver_specific.h" #include "common/io/io.h" +#include "common/library.h" #include "common/properties.h" #include "util/stringUtils.h" #include -#if __aarch64__ && FF_HAVE_DRM - #include +#ifdef FF_HAVE_DRM + #include + #include #include - #include - - // https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h - /* SPDX-License-Identifier: MIT */ - /* Copyright (C) The Asahi Linux Contributors */ - - #define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011 - - #define DRM_ASAHI_GET_PARAMS 0x00 - #define DRM_ASAHI_MAX_CLUSTERS 32 - struct drm_asahi_params_global - { - __u32 unstable_uabi_version; - __u32 pad0; - - __u64 feat_compat; - __u64 feat_incompat; - - __u32 gpu_generation; - __u32 gpu_variant; - __u32 gpu_revision; - __u32 chip_id; - - __u32 num_dies; - __u32 num_clusters_total; - __u32 num_cores_per_cluster; - __u32 num_frags_per_cluster; - __u32 num_gps_per_cluster; - __u32 num_cores_total_active; - __u64 core_masks[DRM_ASAHI_MAX_CLUSTERS]; - - __u32 vm_page_size; - __u32 pad1; - __u64 vm_user_start; - __u64 vm_user_end; - __u64 vm_usc_start; - __u64 vm_usc_end; - __u64 vm_kernel_min_size; - - __u32 max_syncs_per_submission; - __u32 max_commands_per_submission; - __u32 max_commands_in_flight; - __u32 max_attachments; - - __u32 timer_frequency_hz; - __u32 min_frequency_khz; - __u32 max_frequency_khz; - __u32 max_power_mw; - - __u32 result_render_size; - __u32 result_compute_size; - - __u32 firmware_version[4]; - }; - - struct drm_asahi_get_params - { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @param: Parameter group to fetch (MBZ) */ - __u32 param_group; - - /** @pad: MBZ */ - __u32 pad; - - /** @value: User pointer to write parameter struct */ - __u64 pointer; - - /** @value: Size of user buffer, max size supported on return */ - __u64 size; - }; - - enum - { - DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params), - }; #endif +#include "gpu_asahi.h" + #define FF_STR_INDIR(x) #x #define FF_STR(x) FF_STR_INDIR(x) -static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) +static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey) { uint32_t pciDirLength = pciDir->length; ffStrbufAppendS(pciDir, "/driver"); @@ -106,17 +33,17 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer if (slash) { slash++; - ffStrbufSetNS(&gpu->driver, (uint32_t) (resultLength - (slash - pathBuf)), slash); + ffStrbufSetNS(result, (uint32_t) (resultLength - (slash - pathBuf)), slash); } - if (ffStrbufEqualS(&gpu->driver, "nvidia")) + if (ffStrbufEqualS(result, "nvidia")) { if (ffReadFileBuffer("/proc/driver/nvidia/version", buffer)) { if (ffStrbufContainS(buffer, " Open ")) - ffStrbufAppendS(&gpu->driver, " (open source)"); + ffStrbufAppendS(result, " (open source)"); else - ffStrbufAppendS(&gpu->driver, " (proprietary)"); + ffStrbufAppendS(result, " (proprietary)"); } } @@ -126,18 +53,18 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer if (ffReadFileBuffer(pciDir->chars, buffer)) { ffStrbufTrimRightSpace(buffer); - ffStrbufAppendC(&gpu->driver, ' '); - ffStrbufAppend(&gpu->driver, buffer); + ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, buffer); } - else if (ffStrbufEqualS(&gpu->driver, "zx")) + else if (ffStrbufEqualS(result, "zx")) { ffStrbufSubstrBefore(pciDir, pciDirLength); ffStrbufAppendS(pciDir, "/zx_info/driver_version"); if (ffReadFileBuffer(pciDir->chars, buffer)) { ffStrbufTrimRightSpace(buffer); - ffStrbufAppendC(&gpu->driver, ' '); - ffStrbufAppend(&gpu->driver, buffer); + ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, buffer); } } } @@ -145,6 +72,78 @@ static bool pciDetectDriver(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer return true; } +static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) +{ + #if FF_HAVE_DRM + FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 2) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_sensor_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize) + + ffStrbufSetS(buffer, "/dev/dri/"); + ffStrbufAppendS(buffer, drmKey); + FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY); + if (fd < 0) return "Failed to open DRM device"; + + amdgpu_device_handle handle; + uint32_t majorVersion, minorVersion; + if (ffamdgpu_device_initialize(fd, &majorVersion, &minorVersion, &handle) < 0) + return "Failed to initialize AMDGPU device"; + + ffStrbufAppendF(&gpu->driver, " %u.%u", (unsigned) majorVersion, (unsigned) minorVersion); + + uint32_t value; + + if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_VDDNB, sizeof(value), &value) >= 0 && value > 0) + gpu->type = FF_GPU_TYPE_DISCRETE; + else + gpu->type = FF_GPU_TYPE_INTEGRATED; + + struct amdgpu_heap_info heapInfo; + if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) + { + if (gpu->type == FF_GPU_TYPE_DISCRETE) + { + gpu->dedicated.total = heapInfo.heap_size; + gpu->dedicated.used = heapInfo.heap_usage; + } + else + { + gpu->shared.total = heapInfo.heap_size; + gpu->shared.used = heapInfo.heap_usage; + } + } + + if (options->temp) + { + if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) + gpu->temperature = value; + } + + ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle)); + + struct amdgpu_gpu_info gpuInfo; + if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0) + { + gpu->coreCount = (int32_t) gpuInfo.num_shader_engines; + gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u); + gpu->index = gpuInfo.asic_id; + } + + if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0) + gpu->coreUsage = value; + + ffamdgpu_device_deinitialize(handle); + + return NULL; + #else + return "Fastfetch is compiled without libdrm support"; + #endif +} + static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) { // https://www.kernel.org/doc/html/v5.10/gpu/amdgpu.html#mem-info-vis-vram-total @@ -186,6 +185,11 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, ffStrbufAppendS(pciDir, "/mem_info_vis_vram_total"); if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) { + if (gpu->type == FF_GPU_TYPE_DISCRETE) + gpu->dedicated.total = value; + else + gpu->shared.total = value; + ffStrbufSubstrBefore(pciDir, pciDir->length - (uint32_t) strlen("/mem_info_vis_vram_total")); ffStrbufAppendS(pciDir, "/mem_info_vis_vram_used"); if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0))) @@ -306,27 +310,6 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) - { - ffStrbufAppendS(deviceDir, "/revision"); - if (ffReadFileBuffer(deviceDir->chars, buffer)) - { - char* pend; - uint64_t revision = strtoul(buffer->chars, &pend, 16); - if (pend != buffer->chars) - { - char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); - #ifdef FF_CUSTOM_AMDGPU_IDS_PATH - ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name); - #else - ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); - #endif - } - } - ffStrbufSubstrBefore(deviceDir, drmDirPathLength); - } - FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate(); if (gpu->name.length == 0) { @@ -339,13 +322,38 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu, &coreName); } - pciDetectDriver(gpu, deviceDir, buffer, drmKey); + pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) { - pciDetectAmdSpecific(options, gpu, deviceDir, buffer); - ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + bool ok = false; + if (drmKey && options->driverSpecific) + ok = drmDetectAmdSpecific(options, gpu, drmKey, buffer) == NULL; + + if (!ok) + { + pciDetectAmdSpecific(options, gpu, deviceDir, buffer); + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + + ffStrbufAppendS(deviceDir, "/revision"); + if (ffReadFileBuffer(deviceDir->chars, buffer)) + { + char* pend; + uint64_t revision = strtoul(buffer->chars, &pend, 16); + if (pend != buffer->chars) + { + char query[32]; + snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) deviceId, (unsigned) revision); + #ifdef FF_CUSTOM_AMDGPU_IDS_PATH + ffParsePropFile(FF_STR(FF_CUSTOM_AMDGPU_IDS_PATH), query, &gpu->name); + #else + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + #endif + } + } + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + } } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { @@ -407,10 +415,9 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F index += (uint32_t) strlen("apple,agx-t"); FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->index = FF_GPU_INDEX_UNSET; gpu->deviceId = strtoul(buffer->chars + index, NULL, 10); ffStrbufInitStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId)); - if (!gpu->name.length) - ffStrbufAppendF(&gpu->name, "Apple Silicon T%u", (uint32_t) gpu->deviceId); ffStrbufInitStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); ffStrbufInit(&gpu->driver); ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); @@ -421,8 +428,6 @@ 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, drmKey); - #if FF_HAVE_DRM ffStrbufSetS(buffer, "/dev/dri/"); ffStrbufAppendS(buffer, drmKey); @@ -430,12 +435,14 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F if (fd >= 0) { struct drm_asahi_params_global paramsGlobal = {}; - if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params){ + if (ioctl(fd, DRM_IOCTL_ASAHI_GET_PARAMS, &(struct drm_asahi_get_params) { .param_group = DRM_ASAHI_GET_PARAMS, .pointer = (uint64_t) ¶msGlobal, .size = sizeof(paramsGlobal), }) >= 0) { + ffStrbufSetF(&gpu->driver, "asahi %u", paramsGlobal.unstable_uabi_version); + // FIXME: They will introduce ABI breaking changes. Always check the latest version // https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/ if (paramsGlobal.unstable_uabi_version == DRM_ASAHI_UNSTABLE_UABI_VERSION) @@ -443,9 +450,39 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F gpu->coreCount = (int) paramsGlobal.num_cores_total_active; gpu->frequency = paramsGlobal.max_frequency_khz / 1000; gpu->deviceId = paramsGlobal.chip_id; + + if (!gpu->name.length) + { + const char* variant = " Unknown"; + switch (paramsGlobal.gpu_variant) { + case 'G': + variant = ""; + break; + case 'S': + variant = " Pro"; + break; + case 'C': + variant = " Max"; + break; + case 'D': + variant = " Ultra"; + break; + } + ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)", + paramsGlobal.gpu_generation - 12, variant, + paramsGlobal.gpu_generation, paramsGlobal.gpu_variant, + paramsGlobal.gpu_revision + 0xA0); + } } } } + + if (!gpu->driver.length) + { + pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey); + if (!gpu->name.length) + ffStrbufSetF(&gpu->name, "Apple Silicon T%u", (uint32_t) gpu->deviceId); + } #endif return NULL; From 86a96da9ab6d8b8aab51affec3aaf7de43d03c02 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 23 Sep 2024 16:22:11 +0800 Subject: [PATCH 16/65] PhysicalDisk (Linux): cleanup temp detection code --- .../physicaldisk/physicaldisk_linux.c | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index b5a3bbc2a..5d78f57ba 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -7,6 +7,29 @@ #include #include +static double detectNvmeTemp(const char* devName) +{ + char pathSysBlock[PATH_MAX]; + int index = snprintf(pathSysBlock, PATH_MAX, "/sys/block/%s/device/hwmon$/temp1_input", devName); + if (index <= 0) return FF_PHYSICALDISK_TEMP_UNSET; + index -= (int) sizeof("/temp1_input"); + + for (char c = '0'; c <= '9'; c++) // hopefully there's only one digit + { + pathSysBlock[index] = c; + char buffer[64]; + ssize_t size = ffReadFileData(pathSysBlock, sizeof(buffer), buffer); + if (size > 0) + { + buffer[size] = '\0'; + double temp = strtod(buffer, NULL); + return temp > 0 ? temp / 1000 : FF_PHYSICALDISK_TEMP_UNSET; + } + } + + return FF_PHYSICALDISK_TEMP_UNSET; +} + const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) { FF_AUTO_CLOSE_DIR DIR* sysBlockDirp = opendir("/sys/block/"); @@ -157,20 +180,10 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options) } } - device->temperature = FF_PHYSICALDISK_TEMP_UNSET; if (options->temp) - { - const FFlist* tempsResult = ffDetectTemps(); - - FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) - { - if (ffStrStartsWith(devName, value->deviceName.chars)) // nvme0 - nvme0n1 - { - device->temperature = value->value; - break; - } - } - } + device->temperature = detectNvmeTemp(devName); + else + device->temperature = FF_PHYSICALDISK_TEMP_UNSET; } return NULL; From 30ffa4bdd2db809924e3d27bd8bb09f0314e12ec Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 23 Sep 2024 16:36:32 +0800 Subject: [PATCH 17/65] Temps (Linux): simplify --- src/detection/temps/temps_linux.c | 42 ++++++++----------------------- src/detection/temps/temps_linux.h | 2 -- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 89d9f941e..1816e4ca3 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -10,12 +10,19 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) { //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface uint32_t dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); FF_STRBUF_AUTO_DESTROY valueBuffer = ffStrbufCreate(); - - ffStrbufAppendS(dir, "temp1_input"); if(!ffReadFileBuffer(dir->chars, &valueBuffer)) - return false; + { + // Some badly implemented system put temp file in /hwmonN/device + ffStrbufSubstrBefore(dir, dirLength); + ffStrbufAppendS(dir, "/device"); + dirLength = dir->length; + + if(!ffReadFileBuffer(dir->chars, &valueBuffer)) + return false; + } ffStrbufSubstrBefore(dir, dirLength); @@ -29,33 +36,7 @@ static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) ffStrbufTrimRightSpace(&value->name); ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/class"); - if(!ffReadFileBuffer(dir->chars, &valueBuffer)) - { - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/device/class"); - ffReadFileBuffer(dir->chars, &valueBuffer); - } - ffStrbufTrimRightSpace(&valueBuffer); - ffStrbufSubstrBefore(dir, dirLength); - if(valueBuffer.length) - value->deviceClass = (uint32_t) strtoul(valueBuffer.chars, NULL, 16); - - ffStrbufClear(&valueBuffer); - ffStrbufEnsureFree(&valueBuffer, 64); - ffStrbufAppendS(dir, "device"); - ssize_t linkLen = readlink(dir->chars, valueBuffer.chars, valueBuffer.allocated - 1); - if (linkLen > 0) - { - valueBuffer.length = (uint32_t) linkLen; - valueBuffer.chars[linkLen] = 0; - ffStrbufSubstrAfterLastC(&valueBuffer, '/'); - ffStrbufInitMove(&value->deviceName, &valueBuffer); - } - else - ffStrbufInit(&value->deviceName); - - return value->name.length > 0 || value->deviceClass > 0; + return true; } const FFlist* ffDetectTemps(void) @@ -87,7 +68,6 @@ const FFlist* ffDetectTemps(void) FFTempValue* temp = ffListAdd(&result); ffStrbufInit(&temp->name); - temp->deviceClass = 0; if(!parseHwmonDir(&baseDir, temp)) { ffStrbufDestroy(&temp->name); diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h index ccb908b44..e8887c56e 100644 --- a/src/detection/temps/temps_linux.h +++ b/src/detection/temps/temps_linux.h @@ -5,8 +5,6 @@ typedef struct FFTempValue { FFstrbuf name; - FFstrbuf deviceName; - uint32_t deviceClass; double value; } FFTempValue; From a3c0617f2215ae9b5be145ccde421ac2c8533117 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Mon, 23 Sep 2024 20:40:36 +0800 Subject: [PATCH 18/65] GPU: simplify integrated GPU detection --- src/detection/gpu/gpu.h | 2 +- src/detection/gpu/gpu_bsd.c | 13 +++------ src/detection/gpu/gpu_linux.c | 53 +++++++++++++++-------------------- src/detection/gpu/gpu_pci.c | 7 +---- 4 files changed, 28 insertions(+), 47 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 85a51c278..e580d031f 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -49,5 +49,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName); +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 6d07dc029..8e8e80697 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -62,7 +62,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = ((uint64_t) pc->pc_sel.pc_domain << 6) | ((uint64_t) pc->pc_sel.pc_bus << 4) | ((uint64_t) pc->pc_sel.pc_dev << 2) | pc->pc_sel.pc_func; + gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func; gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) @@ -72,12 +72,11 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); } - FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate(); if (gpu->name.length == 0) { if (pciids.length == 0) loadPciIds(&pciids); - ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu, &coreName); + ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); } if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) @@ -118,12 +117,8 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { - if ((coreName.chars[0] == 'D' || coreName.chars[0] == 'S') && - coreName.chars[1] == 'G' && - ffCharIsDigit(coreName.chars[2])) - gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1 - else - gpu->type = FF_GPU_TYPE_INTEGRATED; + // 0000:00:02.0 is reserved for Intel integrated graphics + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; } } } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 14bdaca97..d343de016 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -97,26 +97,6 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult uint32_t value; - if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_VDDNB, sizeof(value), &value) >= 0 && value > 0) - gpu->type = FF_GPU_TYPE_DISCRETE; - else - gpu->type = FF_GPU_TYPE_INTEGRATED; - - struct amdgpu_heap_info heapInfo; - if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) - { - if (gpu->type == FF_GPU_TYPE_DISCRETE) - { - gpu->dedicated.total = heapInfo.heap_size; - gpu->dedicated.used = heapInfo.heap_usage; - } - else - { - gpu->shared.total = heapInfo.heap_size; - gpu->shared.used = heapInfo.heap_usage; - } - } - if (options->temp) { if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) @@ -131,6 +111,22 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult gpu->coreCount = (int32_t) gpuInfo.num_shader_engines; gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u); gpu->index = gpuInfo.asic_id; + gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + + struct amdgpu_heap_info heapInfo; + if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0) + { + if (gpu->type == FF_GPU_TYPE_DISCRETE) + { + gpu->dedicated.total = heapInfo.heap_size; + gpu->dedicated.used = heapInfo.heap_usage; + } + else + { + gpu->shared.total = heapInfo.heap_size; + gpu->shared.used = heapInfo.heap_usage; + } + } } if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_LOAD, sizeof(value), &value) >= 0) @@ -203,17 +199,13 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, } } -static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const FFstrbuf* coreName) +static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) { // Works for Intel GPUs // https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/ - if ((coreName->chars[0] == 'D' || coreName->chars[0] == 'S') && - coreName->chars[1] == 'G' && - ffCharIsDigit(coreName->chars[2])) - gpu->type = FF_GPU_TYPE_DISCRETE; // DG1 / DG2 / SG1 - else - gpu->type = FF_GPU_TYPE_INTEGRATED; + // 0000:00:02.0 is reserved for Intel integrated graphics + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; if (ffStrbufEqualS(&gpu->driver, "xe")) { @@ -305,12 +297,11 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; gpu->type = FF_GPU_TYPE_UNKNOWN; gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->deviceId = ((uint64_t) pciDomain << 6) | ((uint64_t) pciBus << 4) | (deviceId << 2) | pciFunc; + gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc; gpu->frequency = FF_GPU_FREQUENCY_UNSET; if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); - FF_STRBUF_AUTO_DESTROY coreName = ffStrbufCreate(); if (gpu->name.length == 0) { static FFstrbuf pciids; @@ -319,7 +310,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf ffStrbufInit(&pciids); loadPciIds(&pciids); } - ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu, &coreName); + ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); @@ -357,7 +348,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { - pciDetectIntelSpecific(gpu, deviceDir, buffer, &coreName); + pciDetectIntelSpecific(gpu, deviceDir, buffer); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); } else diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index de81f9b60..990e669fe 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,6 +1,6 @@ #include "gpu.h" -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu, FFstrbuf* coreName) +void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) { if (content->length) { @@ -52,11 +52,6 @@ void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint { openingBracket++; ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); - if (coreName) - { - ffStrbufSetNS(coreName, (uint32_t) (openingBracket - start) - 1, start); - ffStrbufTrimRight(coreName, ' '); - } } } if (!gpu->name.length) From 32b6af268637a8f7972acd37efda4bd76994a1e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 23 Sep 2024 22:31:44 +0800 Subject: [PATCH 19/65] GPU (Windows): better Intel GPU type detection --- src/detection/gpu/gpu_windows.c | 93 ++++++++++++++++++--------------- 1 file changed, 51 insertions(+), 42 deletions(-) diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index d82929c29..522b2aed4 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -47,10 +47,21 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->deviceId = 0; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + uint32_t pciBus, pciAddr, pciDev, pciFunc; + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && + SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) + { + pciDev = (pciAddr >> 16) & 0xFFFF; + pciFunc = pciAddr & 0xFFFF; + gpu->deviceId = (pciBus * 1000ull) + (pciDev * 10ull) + pciFunc; + } + wchar_t buffer[256]; if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) ffStrbufSetWS(&gpu->name, buffer); + uint64_t adapterLuid = 0; + FF_HKEY_AUTO_DESTROY hVideoIdKey = SetupDiOpenDevRegKey(hdev, &did, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (!hVideoIdKey) continue; DWORD bufferLen = sizeof(buffer); @@ -61,9 +72,19 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* FF_HKEY_AUTO_DESTROY hDirectxKey = NULL; if (ffRegOpenKeyForRead(HKEY_LOCAL_MACHINE, regDirectxKey, &hDirectxKey, NULL)) { + uint32_t vendorId = 0; + if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) + ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); + + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) + gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + uint64_t dedicatedVideoMemory = 0; if(ffRegReadUint64(hDirectxKey, L"DedicatedVideoMemory", &dedicatedVideoMemory, NULL)) - gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + { + if (gpu->type == FF_GPU_TYPE_UNKNOWN) + gpu->type = dedicatedVideoMemory >= 1024 * 1024 * 1024 ? FF_GPU_TYPE_DISCRETE : FF_GPU_TYPE_INTEGRATED; + } uint64_t dedicatedSystemMemory, sharedSystemMemory; if(ffRegReadUint64(hDirectxKey, L"DedicatedSystemMemory", &dedicatedSystemMemory, NULL) && @@ -73,7 +94,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* gpu->shared.total = sharedSystemMemory; } - ffRegReadUint64(hDirectxKey, L"AdapterLuid", &gpu->deviceId, NULL); + ffRegReadUint64(hDirectxKey, L"AdapterLuid", &adapterLuid, NULL); uint32_t featureLevel = 0; if(ffRegReadUint(hDirectxKey, L"MaxD3D12FeatureLevel", &featureLevel, NULL) && featureLevel) @@ -91,10 +112,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* (unsigned) (driverVersion >> 0) & 0xFFFF ); } - - uint32_t vendorId = 0; - if(ffRegReadUint(hDirectxKey, L"VendorId", &vendorId, NULL) && vendorId) - ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); } } @@ -132,44 +149,36 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* ffStrbufSetStatic(&gpu->vendor, ffGetGPUVendorString(vendorId)); } - uint32_t pciBus, pciAddr; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_BUSNUMBER, NULL, (PBYTE) &pciBus, sizeof(pciBus), NULL) && - SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_ADDRESS, NULL, (PBYTE) &pciAddr, sizeof(pciAddr), NULL)) - { - uint32_t pciDev = (pciAddr >> 16) & 0xFFFF; - uint32_t pciFunc = pciAddr & 0xFFFF; - - detectFn( - &(FFGpuDriverCondition) { - .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID - | (gpu->deviceId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) - | (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), - .pciDeviceId = { - .deviceId = deviceId, - .vendorId = vendorId, - .subSystemId = subSystemId, - .revId = revId, - }, - .pciBusId = { - .domain = 0, - .bus = pciBus, - .device = pciDev, - .func = pciFunc, - }, - .luid = gpu->deviceId, + detectFn( + &(FFGpuDriverCondition) { + .type = FF_GPU_DRIVER_CONDITION_TYPE_DEVICE_ID + | (adapterLuid > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_LUID : 0) + | (vendorId > 0 ? FF_GPU_DRIVER_CONDITION_TYPE_BUS_ID : 0), + .pciDeviceId = { + .deviceId = deviceId, + .vendorId = vendorId, + .subSystemId = subSystemId, + .revId = revId, }, - (FFGpuDriverResult){ - .index = &gpu->index, - .temp = options->temp ? &gpu->temperature : NULL, - .memory = options->driverSpecific ? &gpu->dedicated : NULL, - .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, - .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, - .type = &gpu->type, - .frequency = options->driverSpecific ? &gpu->frequency : NULL, + .pciBusId = { + .domain = 0, + .bus = pciBus, + .device = pciDev, + .func = pciFunc, }, - dllName - ); - } + .luid = adapterLuid, + }, + (FFGpuDriverResult){ + .index = &gpu->index, + .temp = options->temp ? &gpu->temperature : NULL, + .memory = options->driverSpecific ? &gpu->dedicated : NULL, + .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, + .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, + .type = &gpu->type, + .frequency = options->driverSpecific ? &gpu->frequency : NULL, + }, + dllName + ); } } From 3b9d20ddf23b2a6f5c0a3d782e34ae832b3c9f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 23 Sep 2024 22:34:43 +0800 Subject: [PATCH 20/65] Presets: fix examples/24 Fix #24 --- presets/examples/24.jsonc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/presets/examples/24.jsonc b/presets/examples/24.jsonc index 66145db6f..37c27c4b2 100644 --- a/presets/examples/24.jsonc +++ b/presets/examples/24.jsonc @@ -88,7 +88,7 @@ { "type": "disk", "key": "{#90}{$1}│ {#91}Disk {#90}│", - "format": "{$2}{$3}{size-used} / {size-used} ({size-percentage}{$2})" + "format": "{$2}{$3}{size-used} / {size-total} ({size-percentage}{$2})" }, { "type": "poweradapter", From 87d32466f6d07322dc920361bf504a84990f3b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Mon, 23 Sep 2024 22:44:17 +0800 Subject: [PATCH 21/65] GPU (SunOS): fix compiling --- src/detection/gpu/gpu_sunos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 459e377b3..13c87ac97 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -77,7 +77,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* { if (pciids.length == 0) ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); - ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu, NULL); + ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } } From b4325ff205845dec7b731c4bd1b30725e17b12f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 01:42:00 +0000 Subject: [PATCH 22/65] Temps (Linux): simplify --- src/detection/cpu/cpu_linux.c | 18 +--------- src/detection/temps/temps_linux.c | 60 +++++++++++++++---------------- src/detection/temps/temps_linux.h | 8 +---- 3 files changed, 30 insertions(+), 56 deletions(-) diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 4dc9c3801..43c19c09f 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -281,22 +281,6 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) return true; } -static double detectCPUTemp(void) -{ - const FFlist* tempsResult = ffDetectTemps(); - - FF_LIST_FOR_EACH(FFTempValue, value, *tempsResult) - { - if( - ffStrbufFirstIndexS(&value->name, "cpu") < value->name.length || - ffStrbufEqualS(&value->name, "k10temp") || - ffStrbufEqualS(&value->name, "coretemp") - ) return value->value; - } - - return FF_CPU_TEMP_UNSET; -} - FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa) { // Always use the last part of the ISA string. Ref: #590 #1204 @@ -374,7 +358,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if(cpuinfo == NULL) return "fopen(\"/proc/cpuinfo\", \"r\") failed"; - cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET; + cpu->temperature = options->temp ? ffDetectCPUTemp() : FF_CPU_TEMP_UNSET; FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate(); diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c index 1816e4ca3..8577ead2d 100644 --- a/src/detection/temps/temps_linux.c +++ b/src/detection/temps/temps_linux.c @@ -1,61 +1,61 @@ #include "fastfetch.h" #include "common/io/io.h" -#include "common/thread.h" #include "temps_linux.h" -#include #include -static bool parseHwmonDir(FFstrbuf* dir, FFTempValue* value) +static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) { //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface uint32_t dirLength = dir->length; ffStrbufAppendS(dir, "temp1_input"); - FF_STRBUF_AUTO_DESTROY valueBuffer = ffStrbufCreate(); - if(!ffReadFileBuffer(dir->chars, &valueBuffer)) + if(!ffReadFileBuffer(dir->chars, buffer)) { // Some badly implemented system put temp file in /hwmonN/device ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "/device"); + ffStrbufAppendS(dir, "device/"); dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); - if(!ffReadFileBuffer(dir->chars, &valueBuffer)) - return false; + if(!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; } ffStrbufSubstrBefore(dir, dirLength); - value->value = ffStrbufToDouble(&valueBuffer) / 1000; // valueBuffer is millidegree Celsius + double value = ffStrbufToDouble(buffer);// millidegree Celsius - if(value->value != value->value) - return false; + if(value != value) + return 0.0/0.0; ffStrbufAppendS(dir, "name"); - ffReadFileBuffer(dir->chars, &value->name); - ffStrbufTrimRightSpace(&value->name); - ffStrbufSubstrBefore(dir, dirLength); + if (!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; - return true; + ffStrbufTrimRightSpace(buffer); + + if( + ffStrbufContainS(buffer, "cpu") || + ffStrbufEqualS(buffer, "k10temp") || // AMD + ffStrbufEqualS(buffer, "coretemp") // Intel + ) return value / 1000.; + + return false; } -const FFlist* ffDetectTemps(void) +double ffDetectCPUTemp(void) { - static FFlist result; - - if(result.elementSize > 0) - return &result; - - ffListInitA(&result, sizeof(FFTempValue), 16); - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + uint32_t baseDirLength = baseDir.length; FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); if(dirp == NULL) - return &result; + return 0.0/0.0; struct dirent* entry; while((entry = readdir(dirp)) != NULL) @@ -66,16 +66,12 @@ const FFlist* ffDetectTemps(void) ffStrbufAppendS(&baseDir, entry->d_name); ffStrbufAppendC(&baseDir, '/'); - FFTempValue* temp = ffListAdd(&result); - ffStrbufInit(&temp->name); - if(!parseHwmonDir(&baseDir, temp)) - { - ffStrbufDestroy(&temp->name); - --result.length; - } + double result = parseHwmonDir(&baseDir, &buffer); + if (result == result) + return result; ffStrbufSubstrBefore(&baseDir, baseDirLength); } - return &result; + return 0.0/0.0; } diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h index e8887c56e..e4af1a38c 100644 --- a/src/detection/temps/temps_linux.h +++ b/src/detection/temps/temps_linux.h @@ -2,10 +2,4 @@ #include "fastfetch.h" -typedef struct FFTempValue -{ - FFstrbuf name; - double value; -} FFTempValue; - -const FFlist* /* List of FFTempValue */ ffDetectTemps(); +double ffDetectCPUTemp(void); From 9b4053e9dc5a6ddc04a0af45062253f583121f6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 01:51:45 +0000 Subject: [PATCH 23/65] Chore: remove temps_linux --- CMakeLists.txt | 2 - src/detection/battery/battery_linux.c | 1 - src/detection/cpu/cpu_linux.c | 76 +++++++++++++++++- src/detection/gpu/gpu_linux.c | 1 - .../physicaldisk/physicaldisk_linux.c | 1 - src/detection/temps/temps_linux.c | 77 ------------------- src/detection/temps/temps_linux.h | 5 -- 7 files changed, 74 insertions(+), 89 deletions(-) delete mode 100644 src/detection/temps/temps_linux.c delete mode 100644 src/detection/temps/temps_linux.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 47b279241..f55e06d5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -480,7 +480,6 @@ if(LINUX) src/detection/gtk_qt/qt.c src/detection/sound/sound_linux.c src/detection/swap/swap_linux.c - src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c @@ -544,7 +543,6 @@ elseif(ANDROID) src/detection/processes/processes_linux.c src/detection/sound/sound_nosupport.c src/detection/swap/swap_linux.c - src/detection/temps/temps_linux.c src/detection/terminalfont/terminalfont_android.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c diff --git a/src/detection/battery/battery_linux.c b/src/detection/battery/battery_linux.c index 2f073aca1..0d76871c5 100644 --- a/src/detection/battery/battery_linux.c +++ b/src/detection/battery/battery_linux.c @@ -1,6 +1,5 @@ #include "battery.h" #include "common/io/io.h" -#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 43c19c09f..541ac91d9 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -2,13 +2,85 @@ #include "common/io/io.h" #include "common/processing.h" #include "common/properties.h" -#include "detection/temps/temps_linux.h" #include "util/mallocHelper.h" #include "util/stringUtils.h" #include #include #include +#include + +static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) +{ + //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface + uint32_t dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); + + if(!ffReadFileBuffer(dir->chars, buffer)) + { + // Some badly implemented system put temp file in /hwmonN/device + ffStrbufSubstrBefore(dir, dirLength); + ffStrbufAppendS(dir, "device/"); + dirLength = dir->length; + ffStrbufAppendS(dir, "temp1_input"); + + if(!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; + } + + ffStrbufSubstrBefore(dir, dirLength); + + double value = ffStrbufToDouble(buffer);// millidegree Celsius + + if(value != value) + return 0.0/0.0; + + ffStrbufAppendS(dir, "name"); + if (!ffReadFileBuffer(dir->chars, buffer)) + return 0.0/0.0; + + ffStrbufTrimRightSpace(buffer); + + if( + ffStrbufContainS(buffer, "cpu") || + ffStrbufEqualS(buffer, "k10temp") || // AMD + ffStrbufEqualS(buffer, "coretemp") // Intel + ) return value / 1000.; + + return false; +} + +static double detectCPUTemp(void) +{ + FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); + ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); + + FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); + + uint32_t baseDirLength = baseDir.length; + + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); + if(dirp == NULL) + return 0.0/0.0; + + struct dirent* entry; + while((entry = readdir(dirp)) != NULL) + { + if(entry->d_name[0] == '.') + continue; + + ffStrbufAppendS(&baseDir, entry->d_name); + ffStrbufAppendC(&baseDir, '/'); + + double result = parseHwmonDir(&baseDir, &buffer); + if (result == result) + return result; + + ffStrbufSubstrBefore(&baseDir, baseDirLength); + } + + return 0.0/0.0; +} #ifdef __ANDROID__ #include "common/settings.h" @@ -358,7 +430,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if(cpuinfo == NULL) return "fopen(\"/proc/cpuinfo\", \"r\") failed"; - cpu->temperature = options->temp ? ffDetectCPUTemp() : FF_CPU_TEMP_UNSET; + cpu->temperature = options->temp ? detectCPUTemp() : FF_CPU_TEMP_UNSET; FF_STRBUF_AUTO_DESTROY physicalCoresBuffer = ffStrbufCreate(); FF_STRBUF_AUTO_DESTROY cpuMHz = ffStrbufCreate(); diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index d343de016..878039db6 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -1,6 +1,5 @@ #include "detection/gpu/gpu.h" #include "detection/vulkan/vulkan.h" -#include "detection/temps/temps_linux.h" #include "detection/cpu/cpu.h" #include "detection/gpu/gpu_driver_specific.h" #include "common/io/io.h" diff --git a/src/detection/physicaldisk/physicaldisk_linux.c b/src/detection/physicaldisk/physicaldisk_linux.c index 5d78f57ba..1b12d70fb 100644 --- a/src/detection/physicaldisk/physicaldisk_linux.c +++ b/src/detection/physicaldisk/physicaldisk_linux.c @@ -1,7 +1,6 @@ #include "physicaldisk.h" #include "common/io/io.h" #include "common/properties.h" -#include "detection/temps/temps_linux.h" #include "util/stringUtils.h" #include diff --git a/src/detection/temps/temps_linux.c b/src/detection/temps/temps_linux.c deleted file mode 100644 index 8577ead2d..000000000 --- a/src/detection/temps/temps_linux.c +++ /dev/null @@ -1,77 +0,0 @@ -#include "fastfetch.h" -#include "common/io/io.h" -#include "temps_linux.h" - -#include - -static double parseHwmonDir(FFstrbuf* dir, FFstrbuf* buffer) -{ - //https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface - uint32_t dirLength = dir->length; - ffStrbufAppendS(dir, "temp1_input"); - - if(!ffReadFileBuffer(dir->chars, buffer)) - { - // Some badly implemented system put temp file in /hwmonN/device - ffStrbufSubstrBefore(dir, dirLength); - ffStrbufAppendS(dir, "device/"); - dirLength = dir->length; - ffStrbufAppendS(dir, "temp1_input"); - - if(!ffReadFileBuffer(dir->chars, buffer)) - return 0.0/0.0; - } - - ffStrbufSubstrBefore(dir, dirLength); - - double value = ffStrbufToDouble(buffer);// millidegree Celsius - - if(value != value) - return 0.0/0.0; - - ffStrbufAppendS(dir, "name"); - if (!ffReadFileBuffer(dir->chars, buffer)) - return 0.0/0.0; - - ffStrbufTrimRightSpace(buffer); - - if( - ffStrbufContainS(buffer, "cpu") || - ffStrbufEqualS(buffer, "k10temp") || // AMD - ffStrbufEqualS(buffer, "coretemp") // Intel - ) return value / 1000.; - - return false; -} - -double ffDetectCPUTemp(void) -{ - FF_STRBUF_AUTO_DESTROY baseDir = ffStrbufCreateA(64); - ffStrbufAppendS(&baseDir, "/sys/class/hwmon/"); - - FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate(); - - uint32_t baseDirLength = baseDir.length; - - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(baseDir.chars); - if(dirp == NULL) - return 0.0/0.0; - - struct dirent* entry; - while((entry = readdir(dirp)) != NULL) - { - if(entry->d_name[0] == '.') - continue; - - ffStrbufAppendS(&baseDir, entry->d_name); - ffStrbufAppendC(&baseDir, '/'); - - double result = parseHwmonDir(&baseDir, &buffer); - if (result == result) - return result; - - ffStrbufSubstrBefore(&baseDir, baseDirLength); - } - - return 0.0/0.0; -} diff --git a/src/detection/temps/temps_linux.h b/src/detection/temps/temps_linux.h deleted file mode 100644 index e4af1a38c..000000000 --- a/src/detection/temps/temps_linux.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "fastfetch.h" - -double ffDetectCPUTemp(void); From 4ea5d6f4fe4a64f0305d2d8123d2022feadcfa4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 20 Sep 2024 10:46:25 +0800 Subject: [PATCH 24/65] Wifi (macOS): fix protocol detection on Sequoia --- src/detection/wifi/wifi_apple.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/wifi/wifi_apple.m b/src/detection/wifi/wifi_apple.m index 242ac941e..17cebcdfb 100644 --- a/src/detection/wifi/wifi_apple.m +++ b/src/detection/wifi/wifi_apple.m @@ -134,7 +134,7 @@ const char* ffDetectWifi(FFlist* result) ffStrbufSetStatic(&item->conn.protocol, "802.11be (Wi-Fi 7)"); break; default: - if (inf.activePHYMode < 64) + if (inf.activePHYMode < 8) ffStrbufAppendF(&item->conn.protocol, "Unknown (%ld)", inf.activePHYMode); else if (sp || (sp = getWifiInfoBySystemProfiler(inf.interfaceName))) { From 81b0ddb2da5db2fa9eda80bc70b9190f6ae2c921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 10:37:54 +0800 Subject: [PATCH 25/65] Chore: rename temps_apple --- CMakeLists.txt | 2 +- src/detection/battery/battery_apple.c | 2 +- src/detection/cpu/cpu_apple.c | 2 +- src/detection/gpu/gpu_apple.c | 2 +- src/{detection/temps/temps_apple.c => util/apple/smc_temps.c} | 2 +- src/{detection/temps/temps_apple.h => util/apple/smc_temps.h} | 1 - 6 files changed, 5 insertions(+), 6 deletions(-) rename src/{detection/temps/temps_apple.c => util/apple/smc_temps.c} (99%) rename src/{detection/temps/temps_apple.h => util/apple/smc_temps.h} (95%) diff --git a/CMakeLists.txt b/CMakeLists.txt index f55e06d5f..a25c9ac57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -689,7 +689,6 @@ elseif(APPLE) src/detection/processes/processes_bsd.c src/detection/sound/sound_apple.c src/detection/swap/swap_apple.c - src/detection/temps/temps_apple.c src/detection/terminalfont/terminalfont_apple.m src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c @@ -705,6 +704,7 @@ elseif(APPLE) src/detection/zpool/zpool_nosupport.c src/util/apple/cf_helpers.c src/util/apple/osascript.m + src/util/apple/smc_temps.c src/util/platform/FFPlatform_unix.c src/util/binary_apple.c ) diff --git a/src/detection/battery/battery_apple.c b/src/detection/battery/battery_apple.c index 1de81b963..4f3d809b6 100644 --- a/src/detection/battery/battery_apple.c +++ b/src/detection/battery/battery_apple.c @@ -1,7 +1,7 @@ #include "fastfetch.h" #include "battery.h" #include "util/apple/cf_helpers.h" -#include "detection/temps/temps_apple.h" +#include "util/apple/smc_temps.h" #include #include diff --git a/src/detection/cpu/cpu_apple.c b/src/detection/cpu/cpu_apple.c index efdad9502..b08a8b5bc 100644 --- a/src/detection/cpu/cpu_apple.c +++ b/src/detection/cpu/cpu_apple.c @@ -1,6 +1,6 @@ #include "cpu.h" #include "common/sysctl.h" -#include "detection/temps/temps_apple.h" +#include "util/apple/smc_temps.h" #include "util/stringUtils.h" static double detectCpuTemp(const FFstrbuf* cpuName) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 1190a6367..5abf00409 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -1,8 +1,8 @@ #include "gpu.h" #include "common/library.h" #include "detection/cpu/cpu.h" -#include "detection/temps/temps_apple.h" #include "util/apple/cf_helpers.h" +#include "util/apple/smc_temps.h" #include diff --git a/src/detection/temps/temps_apple.c b/src/util/apple/smc_temps.c similarity index 99% rename from src/detection/temps/temps_apple.c rename to src/util/apple/smc_temps.c index c4cef7827..1f9d8179d 100644 --- a/src/detection/temps/temps_apple.c +++ b/src/util/apple/smc_temps.c @@ -1,5 +1,5 @@ #include "fastfetch.h" -#include "temps_apple.h" +#include "smc_temps.h" #include "util/stringUtils.h" #include diff --git a/src/detection/temps/temps_apple.h b/src/util/apple/smc_temps.h similarity index 95% rename from src/detection/temps/temps_apple.h rename to src/util/apple/smc_temps.h index c04b41569..0d6e104c1 100644 --- a/src/detection/temps/temps_apple.h +++ b/src/util/apple/smc_temps.h @@ -1,7 +1,6 @@ #pragma once #include "fastfetch.h" -#include "util/FFlist.h" typedef struct FFTempValue { From 29ae56e76a8fc8258a3fb316248d737468e49db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 10:42:43 +0800 Subject: [PATCH 26/65] TerminalFont: fix hanging when font name is long (kitty) --- src/detection/terminalfont/terminalfont.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/terminalfont/terminalfont.c b/src/detection/terminalfont/terminalfont.c index 0a531b285..e992f7892 100644 --- a/src/detection/terminalfont/terminalfont.c +++ b/src/detection/terminalfont/terminalfont.c @@ -82,7 +82,7 @@ FF_MAYBE_UNUSED static bool detectKitty(const FFstrbuf* exe, FFTerminalFontResul if (ffGetTerminalResponse( "\eP+q6b697474792d71756572792d666f6e745f66616d696c79;6b697474792d71756572792d666f6e745f73697a65\e\\", // kitty-query-font_family;kitty-query-font_size 2, - "\eP1+r%*[^=]=%64[^\e]\e\\\eP1+r%*[^=]=%64[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) + "\eP1+r%*[^=]=%512[^\e]\e\\\eP1+r%*[^=]=%512[^\e]\e\\", fontHex, sizeHex) == NULL && *fontHex && *sizeHex) { // decode hex string for (const char* p = fontHex; p[0] && p[1]; p += 2) From 0c90941a3261f681a49d465fce550ba6ee555b8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 10:58:16 +0800 Subject: [PATCH 27/65] Chore: remove temps_bsd --- CMakeLists.txt | 1 - src/detection/cpu/cpu_bsd.c | 27 ++++++++++++++++++++++++--- src/detection/temps/temps_bsd.c | 24 ------------------------ src/detection/temps/temps_bsd.h | 4 ---- 4 files changed, 24 insertions(+), 32 deletions(-) delete mode 100644 src/detection/temps/temps_bsd.c delete mode 100644 src/detection/temps/temps_bsd.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a25c9ac57..fec2f9729 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -623,7 +623,6 @@ elseif(FreeBSD) src/detection/gtk_qt/qt.c src/detection/sound/sound_bsd.c src/detection/swap/swap_bsd.c - src/detection/temps/temps_bsd.c src/detection/terminalfont/terminalfont_linux.c src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c diff --git a/src/detection/cpu/cpu_bsd.c b/src/detection/cpu/cpu_bsd.c index 4b073f9d5..961cb8478 100644 --- a/src/detection/cpu/cpu_bsd.c +++ b/src/detection/cpu/cpu_bsd.c @@ -1,6 +1,27 @@ #include "cpu.h" #include "common/sysctl.h" -#include "detection/temps/temps_bsd.h" + +static const char* detectCpuTemp(double* current) +{ + int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; + + // In tenth of degrees Kelvin + *current = (double) temp / 10 - 273.15; + return NULL; +} + +static const char* detectThermalTemp(double* current) +{ + int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); + if (temp == -999999) + return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed"; + + // In tenth of degrees Kelvin + *current = (double) temp / 10 - 273.15; + return NULL; +} const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { @@ -46,8 +67,8 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) if (options->temp) { - if (ffDetectCpuTemp(&cpu->temperature) != NULL) - ffDetectThermalTemp(&cpu->temperature); + if (detectCpuTemp(&cpu->temperature) != NULL) + detectThermalTemp(&cpu->temperature); } return NULL; diff --git a/src/detection/temps/temps_bsd.c b/src/detection/temps/temps_bsd.c deleted file mode 100644 index d3160775f..000000000 --- a/src/detection/temps/temps_bsd.c +++ /dev/null @@ -1,24 +0,0 @@ -#include "temps_bsd.h" -#include "common/sysctl.h" - -const char* ffDetectCpuTemp(double* current) -{ - int temp = ffSysctlGetInt("dev.cpu.0.temperature", -999999); - if (temp == -999999) - return "ffSysctlGetInt(\"dev.cpu.0.temperature\") failed"; - - // In tenth of degrees Kelvin - *current = (double) temp / 10 - 273.15; - return NULL; -} - -const char* ffDetectThermalTemp(double* current) -{ - int temp = ffSysctlGetInt("hw.acpi.thermal.tz0.temperature", -999999); - if (temp == -999999) - return "ffSysctlGetInt(\"hw.acpi.thermal.tz0.temperature\") failed"; - - // In tenth of degrees Kelvin - *current = (double) temp / 10 - 273.15; - return NULL; -} diff --git a/src/detection/temps/temps_bsd.h b/src/detection/temps/temps_bsd.h deleted file mode 100644 index 36789740b..000000000 --- a/src/detection/temps/temps_bsd.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -const char* ffDetectCpuTemp(double* current); -const char* ffDetectThermalTemp(double* current); From 5dbd6b9ab812d109b08c3ef9f2a60c13a56779e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Tue, 24 Sep 2024 11:09:51 +0800 Subject: [PATCH 28/65] Chore: remove temps_windows --- CMakeLists.txt | 2 +- src/detection/cpu/cpu_windows.c | 5 +++-- .../{temps/temps_windows.cpp => cpu/cpu_windows.cpp} | 6 +----- src/detection/temps/temps_windows.h | 3 --- 4 files changed, 5 insertions(+), 11 deletions(-) rename src/detection/{temps/temps_windows.cpp => cpu/cpu_windows.cpp} (90%) delete mode 100644 src/detection/temps/temps_windows.h diff --git a/CMakeLists.txt b/CMakeLists.txt index fec2f9729..ea2c93f3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -723,6 +723,7 @@ elseif(WIN32) src/detection/btrfs/btrfs_nosupport.c src/detection/chassis/chassis_windows.c src/detection/cpu/cpu_windows.c + src/detection/cpu/cpu_windows.cpp src/detection/cpucache/cpucache_windows.c src/detection/cpuusage/cpuusage_windows.c src/detection/cursor/cursor_windows.c @@ -757,7 +758,6 @@ elseif(WIN32) src/detection/terminalfont/terminalfont_windows.c src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c - src/detection/temps/temps_windows.cpp src/detection/theme/theme_nosupport.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c diff --git a/src/detection/cpu/cpu_windows.c b/src/detection/cpu/cpu_windows.c index 411ffe6f7..7479ff6d1 100644 --- a/src/detection/cpu/cpu_windows.c +++ b/src/detection/cpu/cpu_windows.c @@ -1,5 +1,4 @@ #include "cpu.h" -#include "detection/temps/temps_windows.h" #include "util/windows/registry.h" #include "util/windows/nt.h" #include "util/mallocHelper.h" @@ -160,6 +159,8 @@ static const char* detectCoreTypes(FFCPUResult* cpu) return NULL; } +const char* detectThermalTemp(double* current, double* critical); + const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) { detectNCores(cpu); @@ -175,7 +176,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu) detectMaxSpeedBySmbios(cpu); if(options->temp) - ffDetectSmbiosTemp(&cpu->temperature, NULL); + detectThermalTemp(&cpu->temperature, NULL); return NULL; } diff --git a/src/detection/temps/temps_windows.cpp b/src/detection/cpu/cpu_windows.cpp similarity index 90% rename from src/detection/temps/temps_windows.cpp rename to src/detection/cpu/cpu_windows.cpp index ac9fccab6..4a961d4c5 100644 --- a/src/detection/temps/temps_windows.cpp +++ b/src/detection/cpu/cpu_windows.cpp @@ -1,11 +1,7 @@ -extern "C" -{ -#include "temps_windows.h" -} #include "util/windows/wmi.hpp" extern "C" -const char* ffDetectSmbiosTemp(double* current, double* critical) +const char* detectThermalTemp(double* current, double* critical) { // Requires Administrator privileges // https://wutils.com/wmi/root/wmi/msacpi_thermalzonetemperature/#properties diff --git a/src/detection/temps/temps_windows.h b/src/detection/temps/temps_windows.h deleted file mode 100644 index 501cc0aa7..000000000 --- a/src/detection/temps/temps_windows.h +++ /dev/null @@ -1,3 +0,0 @@ -#pragma once - -const char* ffDetectSmbiosTemp(double* current, double* critical); From 0414128a557d73be0b88dd6f1e8fb6ccfb03067a Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 24 Sep 2024 16:34:35 +0800 Subject: [PATCH 29/65] GPU (Linux): refactor code to support non-apple SOCs --- src/detection/gpu/gpu_linux.c | 82 ++++++++++++++++++++++------------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 878039db6..81d426fd7 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -257,7 +257,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf uint32_t vendorId, deviceId, subVendorId, subDeviceId; uint8_t classId, subclassId; if (sscanf(buffer->chars + strlen("pci:"), "v%8" SCNx32 "d%8" SCNx32 "sv%8" SCNx32 "sd%8" SCNx32 "bc%2" SCNx8 "sc%2" SCNx8, &vendorId, &deviceId, &subVendorId, &subDeviceId, &classId, &subclassId) != 6) - return "Invalid modalias string"; + return "Failed to parse pci modalias"; if (classId != 0x03 /*PCI_BASE_CLASS_DISPLAY*/) return "Not a GPU device"; @@ -398,25 +398,11 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf #if __aarch64__ -FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) +FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FFstrbuf* buffer, const char* drmKey) { - uint32_t index = ffStrbufFirstIndexS(buffer, "apple,agx-t"); - if (index == buffer->length) return "display-subsystem?"; - index += (uint32_t) strlen("apple,agx-t"); - - FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); - gpu->index = FF_GPU_INDEX_UNSET; - gpu->deviceId = strtoul(buffer->chars + index, NULL, 10); - ffStrbufInitStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId)); - ffStrbufInitStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); - ffStrbufInit(&gpu->driver); - ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); - gpu->temperature = FF_GPU_TEMP_UNSET; - gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; - gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; - gpu->type = FF_GPU_TYPE_INTEGRATED; - gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; - gpu->frequency = FF_GPU_FREQUENCY_UNSET; + if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1) + ffStrbufSetStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId)); + ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE); #if FF_HAVE_DRM ffStrbufSetS(buffer, "/dev/dri/"); @@ -431,7 +417,7 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F .size = sizeof(paramsGlobal), }) >= 0) { - ffStrbufSetF(&gpu->driver, "asahi %u", paramsGlobal.unstable_uabi_version); + ffStrbufAppendF(&gpu->driver, " %u", paramsGlobal.unstable_uabi_version); // FIXME: They will introduce ABI breaking changes. Always check the latest version // https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/ @@ -466,19 +452,57 @@ FF_MAYBE_UNUSED static const char* detectAsahi(FFlist* gpus, FFstrbuf* buffer, F } } } - - if (!gpu->driver.length) - { - pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey); - if (!gpu->name.length) - ffStrbufSetF(&gpu->name, "Apple Silicon T%u", (uint32_t) gpu->deviceId); - } #endif return NULL; } #endif +static const char* detectOf(FFlist* gpus, FFstrbuf* buffer, FFstrbuf* drmDir, const char* drmKey) +{ + char compatible[256]; // vendor,model-name + if (sscanf(buffer->chars + strlen("of:"), "NgpuT%*[^C]C%256[^C]", compatible) != 1) + return "Failed to parse of modalias or not a GPU device"; + + char* name = strchr(compatible, ','); + if (name) + { + *name = '\0'; + ++name; + } + + FFGPUResult* gpu = (FFGPUResult*)ffListAdd(gpus); + gpu->index = FF_GPU_INDEX_UNSET; + gpu->deviceId = 0; + ffStrbufInit(&gpu->name); + ffStrbufInit(&gpu->vendor); + ffStrbufInit(&gpu->driver); + ffStrbufInitF(&gpu->platformApi, "DRM (%s)", drmKey); + gpu->temperature = FF_GPU_TEMP_UNSET; + gpu->coreCount = FF_GPU_CORE_COUNT_UNSET; + gpu->coreUsage = FF_GPU_CORE_USAGE_UNSET; + gpu->type = FF_GPU_TYPE_INTEGRATED; + gpu->dedicated.total = gpu->dedicated.used = gpu->shared.total = gpu->shared.used = FF_GPU_VMEM_SIZE_UNSET; + gpu->frequency = FF_GPU_FREQUENCY_UNSET; + + pciDetectDriver(&gpu->driver, drmDir, buffer, drmKey); + + #ifdef __aarch64__ + if (ffStrbufEqualS(&gpu->driver, "asahi")) + drmDetectAsahiSpecific(gpu, name, buffer, drmKey); + #endif + + if (!gpu->name.length) + ffStrbufSetS(&gpu->name, name ? name : compatible); + if (!gpu->vendor.length && name) + { + compatible[0] = (char) toupper(compatible[0]); + ffStrbufSetS(&gpu->vendor, compatible); + } + + return NULL; +} + static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) { FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64); @@ -507,10 +531,8 @@ static const char* drmDetectGPUs(const FFGPUOptions* options, FFlist* gpus) if (ffStrbufStartsWithS(&buffer, "pci:")) detectPci(options, gpus, &buffer, &drmDir, entry->d_name); - #ifdef __aarch64__ else if (ffStrbufStartsWithS(&buffer, "of:")) - detectAsahi(gpus, &buffer, &drmDir, entry->d_name); - #endif + detectOf(gpus, &buffer, &drmDir, entry->d_name); ffStrbufSubstrBefore(&drmDir, drmDirLength); } From 582b0fa08781706e4cc01a9318c29f0044c5b26e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Wed, 25 Sep 2024 09:36:20 +0800 Subject: [PATCH 30/65] Monitor (Linux): prefer DRM --- src/detection/monitor/monitor_linux.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/detection/monitor/monitor_linux.c b/src/detection/monitor/monitor_linux.c index ecf3bef34..48d52d0b0 100644 --- a/src/detection/monitor/monitor_linux.c +++ b/src/detection/monitor/monitor_linux.c @@ -176,7 +176,7 @@ FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) { const char* drmDirPath = "/sys/class/drm/"; - DIR* dirp = opendir(drmDirPath); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath); if(dirp == NULL) return "opendir(drmDirPath) == NULL"; @@ -232,23 +232,23 @@ FF_MAYBE_UNUSED static const char* detectByDrm(FFlist* results) ffStrbufSubstrBefore(&drmDir, drmDirLength); } - closedir(dirp); return NULL; } #endif // __linux__ const char* ffDetectMonitor(FFlist* results) { - const char* error = "Fastfetch was compiled without xrandr support"; + const char* error = NULL; + + #if defined(__linux__) + error = detectByDrm(results); + if (!error && results->length > 0) return NULL; + #endif #ifdef FF_HAVE_XRANDR error = detectByXrandr(results); if (!error) return NULL; #endif - #if defined(__linux__) - error = detectByDrm(results); - #endif - - return error; + return "Fastfetch was compiled without xrandr support"; } From ae6817e106b41fc422585b0fed3bb7d57535c863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Sep 2024 16:24:51 +0800 Subject: [PATCH 31/65] GPU: simplify logic of pci.ids file loading --- src/detection/gpu/gpu.h | 2 +- src/detection/gpu/gpu_bsd.c | 20 +----------------- src/detection/gpu/gpu_linux.c | 8 +------ src/detection/gpu/gpu_pci.c | 40 ++++++++++++++++++++++++++++++++++- src/detection/gpu/gpu_sunos.c | 6 +----- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index e580d031f..700caf773 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -49,5 +49,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); +void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 8e8e80697..330c4dcc0 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -8,20 +8,6 @@ #include #include #include -#include - -static bool loadPciIds(FFstrbuf* pciids) -{ - // https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h - - ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids); - if (pciids->length > 0) return true; - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids); - if (pciids->length > 0) return true; - - return false; -} const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) { @@ -45,8 +31,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (pcio.status == PCI_GETCONF_ERROR) return "ioctl(fd, PCIOCGETCONF, &pc) returned error"; - FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - for (uint32_t i = 0; i < pcio.num_matches; ++i) { struct pci_conf* pc = &confs[i]; @@ -74,9 +58,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (gpu->name.length == 0) { - if (pciids.length == 0) - loadPciIds(&pciids); - ffGPUParsePciIds(&pciids, pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + ffGPUParsePciIds(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); } if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 81d426fd7..585fcb42c 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -303,13 +303,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (gpu->name.length == 0) { - static FFstrbuf pciids; - if (pciids.chars == NULL) - { - ffStrbufInit(&pciids); - loadPciIds(&pciids); - } - ffGPUParsePciIds(&pciids, subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + ffGPUParsePciIds(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index 990e669fe..7176120d5 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,7 +1,45 @@ #include "gpu.h" -void ffGPUParsePciIds(FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +#ifdef __FreeBSD__ +#include +#endif + +static const FFstrbuf* loadPciIds() { + static FFstrbuf pciids; + + if (pciids.chars) return &pciids; + ffStrbufinit(&pciids); + + #ifdef FF_CUSTOM_PCI_IDS_PATH + + ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids); + + #else // FF_CUSTOM_PCI_IDS_PATH + + #if __linux__ + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids); + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian? + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids); + #elif __FreeBSD__ + // https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h + ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids); + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids); + #elif __sun + ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); + #endif + + #endif // FF_CUSTOM_PCI_IDS_PATH + + return &pciids; +} + +void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +{ + const FFstrbuf* content = loadPciIds(); if (content->length) { char buffer[32]; diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 13c87ac97..0a8f27a33 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -20,8 +20,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (!ffStrbufStartsWithS(&buffer, "\npci ")) return "Invalid scanpci result"; - FF_STRBUF_AUTO_DESTROY pciids = ffStrbufCreate(); - // pci bus 0x0000 cardnum 0x00 function 0x00: vendor 0x1414 device 0x008e // Device unknown // CardVendor 0x0000 card 0x0000 (Card unknown) @@ -75,9 +73,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (gpu->name.length == 0) { - if (pciids.length == 0) - ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); - ffGPUParsePciIds(&pciids, (uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + ffGPUParsePciIds((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } } From 96d885e93ad8ca966c7d02a932cd49f31f7dd6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Sep 2024 16:41:55 +0800 Subject: [PATCH 32/65] GPU: embed pci.ids into fastfetch --- CMakeLists.txt | 18 ++++++- scripts/gen-pciids.py | 89 +++++++++++++++++++++++++++++++++++ src/common/init.c | 3 ++ src/detection/gpu/gpu.h | 2 +- src/detection/gpu/gpu_bsd.c | 2 +- src/detection/gpu/gpu_linux.c | 25 +--------- src/detection/gpu/gpu_pci.c | 88 ++++++++++++++++++++++++++++++---- src/detection/gpu/gpu_sunos.c | 2 +- 8 files changed, 191 insertions(+), 38 deletions(-) create mode 100644 scripts/gen-pciids.py diff --git a/CMakeLists.txt b/CMakeLists.txt index ea2c93f3a..655e47923 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,6 +80,7 @@ option(BUILD_TESTS "Build tests" OFF) # Also create test executables option(SET_TWEAK "Add tweak to project version" ON) # This is set to off by github actions for release builds option(IS_MUSL "Build with musl libc" OFF) # Used by Github Actions option(INSTALL_LICENSE "Install license into /usr/share/licenses" ON) +option(ENABLE_EMBEDDED_PCIIDS "Embed pci.ids into fastfetch, requires `python`" OFF) set(BINARY_LINK_TYPE_OPTIONS dlopen dynamic static) set(BINARY_LINK_TYPE dlopen CACHE STRING "How to link fastfetch") @@ -254,6 +255,16 @@ else() file(READ "src/data/help.json" DATATEXT_JSON_HELP) endif() +if(ENABLE_EMBEDDED_PCIIDS AND NOT EXISTS "fastfetch_pciids.c.inc") + if(Python_FOUND) + execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/scripts/gen-pciids.py" + OUTPUT_FILE "fastfetch_pciids.c.inc") + else() + message(STATUS "Python3 is not found, 'fastfetch_pciids.c.inc' will not be generated") + set(ENABLE_EMBEDDED_PCIIDS OFF) + endif() +endif() + fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP) fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE) fastfetch_load_text(src/data/help_footer.txt DATATEXT_HELP_FOOTER) @@ -1130,14 +1141,17 @@ if(ENABLE_LIBZFS) endif() endif() - if(ENABLE_THREADS) - target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_THREADS=1) if(CMAKE_USE_PTHREADS_INIT) #Threads::Threads is not set for WIN32 target_link_libraries(libfastfetch PRIVATE Threads::Threads) endif() endif() +if(ENABLE_EMBEDDED_PCIIDS) + target_compile_definitions(libfastfetch PRIVATE FF_HAVE_EMBEDDED_PCIIDS=1) +endif() + if(LINUX) target_link_libraries(libfastfetch PRIVATE "m" diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py new file mode 100644 index 000000000..bc98fec55 --- /dev/null +++ b/scripts/gen-pciids.py @@ -0,0 +1,89 @@ +from requests import get as http_get + +class PciDeviceModel: + def __init__(self, id: int, name: str): + self.id = id + self.name = name + +class PciVendorModel: + def __init__(self, id: int, name: str): + self.id = id + self.name = name + self.devices: list[PciDeviceModel] = [] + +def main(keep_vendor_list: set[int]): + vendors: list[PciVendorModel] = [] + try: + with open('pci.ids', 'r') as f: + full_text = f.read() + except FileNotFoundError: + response = http_get('https://pci-ids.ucw.cz/v2.2/pci.ids') + full_text = response.text + + dev_list_text = full_text[:full_text.rfind('\n\n\n')] # remove known classes + for line in dev_list_text.split('\n'): + if not line or line[0] == '#': + continue + if line[0] != '\t': + id, name = line.split(' ', maxsplit=1) + vendors.append(PciVendorModel(int(id, 16), name)) + elif line[1] != '\t': + id, name = line[1:].split(' ', maxsplit=1) + vendors[-1].devices.append(PciDeviceModel(int(id, 16), name)) + + code = """\ +#include +#include + +typedef struct FFPciDevice +{ + const uint32_t id; + const char* name; +} FFPciDevice; + +typedef struct FFPciVendor +{ + const uint32_t id; + const char* name; + const FFPciDevice* devices; + const uint32_t nDevices; +} FFPciVendor; +""" + + if keep_vendor_list: + vendors = [vendor for vendor in vendors if vendor.id in keep_vendor_list] + + for vendor in vendors: + if vendor.devices: + code += f""" +// {vendor.name} +static const FFPciDevice pciDevices_{vendor.id:04X}[] = {{ + {',\n '.join(f'{{ 0x{device.id:04X}, "{device.name.replace('"', '\\"')}" }}' for device in vendor.devices)}, + {{}}, +}}; +""" + + code += f""" +const FFPciVendor ffPciVendors[] = {{ + {',\n '.join(f'{{ 0x{vendor.id:04X}, "{vendor.name.replace('"', '\\"')}", {vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL"}, {len(vendor.devices)} }}' for vendor in vendors)}, + {{}}, +}};""" + + print(code) + +if __name__ == '__main__': + # From + main({ + 0x106b, # Apple + 0x1002, 0x1022, # AMD + 0x8086, 0x8087, 0x03e7, # Intel + 0x0955, 0x10de, 0x12d2, # Nvidia + 0x1ed5, # MThreads + 0x5143, # Qualcomm + 0x14c3, # MTK + 0x15ad, # VMware + 0x1af4, # RedHat + 0x1ab8, # Parallel + 0x1414, # Microsoft + 0x108e, # Oracle + }) diff --git a/src/common/init.c b/src/common/init.c index 8bf6f60e1..9845ff526 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -260,6 +260,9 @@ void ffListFeatures(void) #if FF_HAVE_LINUX_WIRELESS "linux/wireless\n" #endif + #if FF_HAVE_EMBEDDED_PCIIDS + "Embedded pciids\n" + #endif "" , stdout); } diff --git a/src/detection/gpu/gpu.h b/src/detection/gpu/gpu.h index 700caf773..3edd78fc1 100644 --- a/src/detection/gpu/gpu.h +++ b/src/detection/gpu/gpu.h @@ -49,5 +49,5 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus); const char* ffGetGPUVendorString(unsigned vendorId); #if defined(__linux__) || defined(__FreeBSD__) || defined(__sun) -void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); +void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu); #endif diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 330c4dcc0..2f1d9cc58 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -58,7 +58,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) if (gpu->name.length == 0) { - ffGPUParsePciIds(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); } if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 585fcb42c..0db1373a7 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -228,29 +228,6 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0); } -static bool loadPciIds(FFstrbuf* pciids) -{ - #ifdef FF_CUSTOM_PCI_IDS_PATH - - ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids); - if (pciids->length > 0) return true; - - #else - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids); - if (pciids->length > 0) return true; - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian? - if (pciids->length > 0) return true; - - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids); - if (pciids->length > 0) return true; - - #endif - - return false; -} - static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) { const uint32_t drmDirPathLength = deviceDir->length; @@ -303,7 +280,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (gpu->name.length == 0) { - ffGPUParsePciIds(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index 7176120d5..5aa86a7b8 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -1,15 +1,21 @@ #include "gpu.h" +#include "common/io/io.h" +#include #ifdef __FreeBSD__ #include #endif +#if FF_HAVE_EMBEDDED_PCIIDS +#include "fastfetch_pciids.c.inc" +#endif + static const FFstrbuf* loadPciIds() { static FFstrbuf pciids; if (pciids.chars) return &pciids; - ffStrbufinit(&pciids); + ffStrbufInit(&pciids); #ifdef FF_CUSTOM_PCI_IDS_PATH @@ -18,16 +24,18 @@ static const FFstrbuf* loadPciIds() #else // FF_CUSTOM_PCI_IDS_PATH #if __linux__ - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", pciids); + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/hwdata/pci.ids", &pciids); if (pciids.length == 0) - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", pciids); // debian? - if (pciids.length == 0) - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", pciids); + { + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/misc/pci.ids", &pciids); // debian? + if (pciids.length == 0) + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/local/share/hwdata/pci.ids", &pciids); + } #elif __FreeBSD__ // https://github.com/freebsd/freebsd-src/blob/main/usr.sbin/pciconf/pathnames.h - ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", pciids); + ffReadFileBuffer(_PATH_LOCALBASE "/share/pciids/pci.ids", &pciids); if (pciids.length == 0) - ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", pciids); + ffReadFileBuffer(FASTFETCH_TARGET_DIR_USR "/share/pciids/pci.ids", &pciids); #elif __sun ffReadFileBuffer(FASTFETCH_TARGET_DIR_ROOT "/usr/share/hwdata/pci.ids", &pciids); #endif @@ -37,9 +45,8 @@ static const FFstrbuf* loadPciIds() return &pciids; } -void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) { - const FFstrbuf* content = loadPciIds(); if (content->length) { char buffer[32]; @@ -112,3 +119,66 @@ void ffGPUParsePciIds(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUR ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); } } + +#if FF_HAVE_EMBEDDED_PCIIDS +static inline int pciDeviceCmp(const FFPciDevice* a, const FFPciDevice* b) +{ + return (int) a->id - (int) b->id; +} + +static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +{ + for (const FFPciVendor* pvendor = ffPciVendors; pvendor->name; pvendor++) + { + if (pvendor->id != vendor) continue; + + if (!gpu->vendor.length) + ffStrbufSetS(&gpu->vendor, pvendor->name); + + const FFPciDevice* pdevice = (const FFPciDevice*) bsearch(&device, pvendor->devices, pvendor->nDevices, sizeof(FFPciDevice), (void*) pciDeviceCmp); + + if (pdevice) + { + uint32_t nameLen = (uint32_t) strlen(pdevice->name); + const char* closingBracket = pdevice->name + nameLen - 1; + if (*closingBracket == ']') + { + const char* openingBracket = memrchr(pdevice->name, '[', nameLen - 1); + if (openingBracket) + { + openingBracket++; + ffStrbufSetNS(&gpu->name, (uint32_t) (closingBracket - openingBracket), openingBracket); + } + } + if (!gpu->name.length) + ffStrbufSetNS(&gpu->name, nameLen, pdevice->name); + return true; + } + + if (!gpu->name.length) + { + const char* subclassStr; + switch (subclass) + { + case 0 /*PCI_CLASS_DISPLAY_VGA*/: subclassStr = " (VGA compatible)"; break; + case 1 /*PCI_CLASS_DISPLAY_XGA*/: subclassStr = " (XGA compatible)"; break; + case 2 /*PCI_CLASS_DISPLAY_3D*/: subclassStr = " (3D)"; break; + default: subclassStr = ""; break; + } + + ffStrbufSetF(&gpu->name, "%s Device %04X%s", gpu->vendor.length ? gpu->vendor.chars : "Unknown", device, subclassStr); + } + return true; + } + return false; +} +#endif + +void ffGPUFillVendorAndName(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) +{ + #if FF_HAVE_EMBEDDED_PCIIDS + bool ok = loadPciidsInc(subclass, vendor, device, gpu); + if (ok) return; + #endif + return parsePciIdsFile(loadPciIds(), subclass, vendor, device, gpu); +} diff --git a/src/detection/gpu/gpu_sunos.c b/src/detection/gpu/gpu_sunos.c index 0a8f27a33..6e8d19460 100644 --- a/src/detection/gpu/gpu_sunos.c +++ b/src/detection/gpu/gpu_sunos.c @@ -73,7 +73,7 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* if (gpu->name.length == 0) { - ffGPUParsePciIds((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + ffGPUFillVendorAndName((uint8_t) subclass, (uint16_t) vendorId, (uint16_t) deviceId, gpu); } } From f496e6d965c61f03c20ea1f68d848be89b05a9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Wed, 25 Sep 2024 22:55:57 +0800 Subject: [PATCH 33/65] TPM: add new module --- CMakeLists.txt | 9 ++- doc/json_schema.json | 5 ++ src/common/modules.c | 1 + src/detection/tpm/tpm.h | 11 +++ src/detection/tpm/tpm_linux.c | 22 ++++++ src/detection/tpm/tpm_nosupport.c | 6 ++ src/detection/tpm/tpm_windows.c | 82 ++++++++++++++++++++ src/modules/modules.h | 1 + src/modules/options.h | 1 + src/modules/tpm/option.h | 11 +++ src/modules/tpm/tpm.c | 124 ++++++++++++++++++++++++++++++ src/modules/tpm/tpm.h | 9 +++ src/options/modules.c | 2 + src/options/modules.h | 1 + 14 files changed, 284 insertions(+), 1 deletion(-) create mode 100644 src/detection/tpm/tpm.h create mode 100644 src/detection/tpm/tpm_linux.c create mode 100644 src/detection/tpm/tpm_nosupport.c create mode 100644 src/detection/tpm/tpm_windows.c create mode 100644 src/modules/tpm/option.h create mode 100644 src/modules/tpm/tpm.c create mode 100644 src/modules/tpm/tpm.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 655e47923..46c656957 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -405,6 +405,7 @@ set(LIBFASTFETCH_SRC src/modules/terminalsize/terminalsize.c src/modules/theme/theme.c src/modules/title/title.c + src/modules/tpm/tpm.c src/modules/uptime/uptime.c src/modules/users/users.c src/modules/version/version.c @@ -495,6 +496,7 @@ if(LINUX) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_linux.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -558,6 +560,7 @@ elseif(ANDROID) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_linux.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_nosupport.c @@ -638,6 +641,7 @@ elseif(FreeBSD) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -703,6 +707,7 @@ elseif(APPLE) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_apple.m @@ -770,6 +775,7 @@ elseif(WIN32) src/detection/terminalshell/terminalshell_windows.c src/detection/terminalsize/terminalsize_windows.c src/detection/theme/theme_nosupport.c + src/detection/tpm/tpm_windows.c src/detection/uptime/uptime_windows.c src/detection/users/users_windows.c src/detection/wallpaper/wallpaper_windows.c @@ -854,6 +860,7 @@ elseif(SunOS) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c + src/detection/tpm/tpm_nosupport.c src/detection/uptime/uptime_sunos.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c @@ -1179,7 +1186,7 @@ elseif(APPLE) PRIVATE "-weak_framework Apple80211" ) elseif(WIN32) - target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0601) + target_compile_definitions(libfastfetch PRIVATE -D_WIN32_WINNT=0x0A00) target_link_libraries(libfastfetch PRIVATE "dwmapi" PRIVATE "gdi32" diff --git a/doc/json_schema.json b/doc/json_schema.json index 0ebda7d2c..04266e383 100644 --- a/doc/json_schema.json +++ b/doc/json_schema.json @@ -706,6 +706,7 @@ "terminaltheme", "title", "theme", + "tpm", "uptime", "users", "version", @@ -865,6 +866,10 @@ "const": "theme", "description": "Print current theme of desktop environment" }, + { + "const": "tpm", + "description": "Print info of Trusted Platform Module (TPM) Security Device" + }, { "const": "uptime", "description": "Print how long system has been running" diff --git a/src/common/modules.c b/src/common/modules.c index 232c555f0..4e8ae69e4 100644 --- a/src/common/modules.c +++ b/src/common/modules.c @@ -137,6 +137,7 @@ static FFModuleBaseInfo* T[] = { (void*) &instance.config.modules.terminalTheme, (void*) &instance.config.modules.title, (void*) &instance.config.modules.theme, + (void*) &instance.config.modules.tpm, NULL, }; diff --git a/src/detection/tpm/tpm.h b/src/detection/tpm/tpm.h new file mode 100644 index 000000000..d8bc72b54 --- /dev/null +++ b/src/detection/tpm/tpm.h @@ -0,0 +1,11 @@ +#pragma once + +#include "fastfetch.h" + +typedef struct FFTPMResult +{ + FFstrbuf version; + FFstrbuf interfaceType; +} FFTPMResult; + +const char* ffDetectTPM(FFTPMResult* result); diff --git a/src/detection/tpm/tpm_linux.c b/src/detection/tpm/tpm_linux.c new file mode 100644 index 000000000..14e8be369 --- /dev/null +++ b/src/detection/tpm/tpm_linux.c @@ -0,0 +1,22 @@ +#include "tpm.h" +#include "common/io/io.h" + +const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +{ + if (ffReadFileBuffer("/sys/class/tpm/tpm0/tpm_version_major", &result->version)) + { + ffStrbufTrimRightSpace(&result->version); + if (ffStrbufEqualS(&result->version, "2")) + ffStrbufSetStatic(&result->version, "2.0"); + + return NULL; + } + + if (ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) + { + ffStrbufSetStatic(&result->version, "unknown"); + return NULL; + } + + return "TPM device is not found"; +} diff --git a/src/detection/tpm/tpm_nosupport.c b/src/detection/tpm/tpm_nosupport.c new file mode 100644 index 000000000..7865f70b5 --- /dev/null +++ b/src/detection/tpm/tpm_nosupport.c @@ -0,0 +1,6 @@ +#include "tpm.h" + +const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +{ + return "Not supported on this platform"; +} diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c new file mode 100644 index 000000000..2837822d8 --- /dev/null +++ b/src/detection/tpm/tpm_windows.c @@ -0,0 +1,82 @@ +#include "tpm.h" +#include "common/library.h" + +// #include + +#define TBS_SUCCESS 0u +#define TBS_E_INTERNAL_ERROR 0x80284001u +#define TBS_E_INVALID_CONTEXT 0x80284004u +typedef UINT32 TBS_RESULT; + +#define TPM_VERSION_UNKNOWN 0 +#define TPM_VERSION_12 1 +#define TPM_VERSION_20 2 + +#define TPM_IFTYPE_UNKNOWN 0 +#define TPM_IFTYPE_1 1 // for 1.2 - use I/O-port or MMIO +#define TPM_IFTYPE_TRUSTZONE 2 // 2.0: Trustzone +#define TPM_IFTYPE_HW 3 // 2.0: HW TPM +#define TPM_IFTYPE_EMULATOR 4 // 2.0: SW-emulator +#define TPM_IFTYPE_SPB 5 // 2.0: SPB attached + +typedef struct _TPM_DEVICE_INFO +{ + UINT32 structVersion; // = 1 for now + UINT32 tpmVersion; // 1.2 / 2.0 + UINT32 tpmInterfaceType; // HW, simulator, ... + UINT32 tpmImpRevision; // code-drop revision, + // implenmentation-specific +} TPM_DEVICE_INFO, *PTPM_DEVICE_INFO; +typedef const TPM_DEVICE_INFO *PCTPM_DEVICE_INFO; + +TBS_RESULT WINAPI +Tbsi_GetDeviceInfo( + _In_ UINT32 Size, + _Out_writes_bytes_(Size) PVOID Info); + +const char* ffDetectTPM(FFTPMResult* result) +{ + FF_LIBRARY_LOAD(tbs, "dlopen TBS" FF_LIBRARY_EXTENSION " failed", "TBS" FF_LIBRARY_EXTENSION, -1) + FF_LIBRARY_LOAD_SYMBOL_MESSAGE(tbs, Tbsi_GetDeviceInfo) + + TPM_DEVICE_INFO deviceInfo = {}; + TBS_RESULT code = ffTbsi_GetDeviceInfo(sizeof(deviceInfo), &deviceInfo); + if (code != TBS_SUCCESS) + return code == (TBS_RESULT) TBS_E_INVALID_CONTEXT ? "TPM device is not found" : "Tbsi_GetDeviceInfo() failed"; + + switch (deviceInfo.tpmVersion) + { + case TPM_VERSION_12: + ffStrbufSetStatic(&result->version, "1.2"); + break; + case TPM_VERSION_20: + ffStrbufSetStatic(&result->version, "2.0"); + break; + default: + ffStrbufSetStatic(&result->version, "unknown"); + break; + } + + switch (deviceInfo.tpmInterfaceType) + { + case TPM_IFTYPE_1: + ffStrbufSetStatic(&result->interfaceType, "I/O-port or MMIO"); + break; + case TPM_IFTYPE_TRUSTZONE: + ffStrbufSetStatic(&result->interfaceType, "Trustzone"); + break; + case TPM_IFTYPE_HW: + ffStrbufSetStatic(&result->interfaceType, "HW TPM"); + break; + case TPM_IFTYPE_EMULATOR: + ffStrbufSetStatic(&result->interfaceType, "SW-emulator"); + break; + case TPM_IFTYPE_SPB: + ffStrbufSetStatic(&result->interfaceType, "SPB attached"); + break; + default: + break; + } + + return NULL; +} diff --git a/src/modules/modules.h b/src/modules/modules.h index 84d9e6fcb..4f9fa7a40 100644 --- a/src/modules/modules.h +++ b/src/modules/modules.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/terminaltheme.h" #include "modules/theme/theme.h" #include "modules/title/title.h" +#include "modules/tpm/tpm.h" #include "modules/uptime/uptime.h" #include "modules/users/users.h" #include "modules/version/version.h" diff --git a/src/modules/options.h b/src/modules/options.h index 2677d2515..783757d3a 100644 --- a/src/modules/options.h +++ b/src/modules/options.h @@ -62,6 +62,7 @@ #include "modules/terminaltheme/option.h" #include "modules/theme/option.h" #include "modules/title/option.h" +#include "modules/tpm/option.h" #include "modules/uptime/option.h" #include "modules/users/option.h" #include "modules/version/option.h" diff --git a/src/modules/tpm/option.h b/src/modules/tpm/option.h new file mode 100644 index 000000000..d98c21df2 --- /dev/null +++ b/src/modules/tpm/option.h @@ -0,0 +1,11 @@ +#pragma once + +// This file will be included in "fastfetch.h", do NOT put unnecessary things here + +#include "common/option.h" + +typedef struct FFTPMOptions +{ + FFModuleBaseInfo moduleInfo; + FFModuleArgs moduleArgs; +} FFTPMOptions; diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c new file mode 100644 index 000000000..f9b7a1e5d --- /dev/null +++ b/src/modules/tpm/tpm.c @@ -0,0 +1,124 @@ +#include "common/printing.h" +#include "common/jsonconfig.h" +#include "detection/tpm/tpm.h" +#include "modules/tpm/tpm.h" +#include "util/stringUtils.h" + +#define FF_TPM_NUM_FORMAT_ARGS 2 + +void ffPrintTPM(FFTPMOptions* options) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .interfaceType = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "%s", error); + return; + } + + if(options->moduleArgs.outputFormat.length == 0) + { + ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); + ffStrbufPutTo(&result.version, stdout); + } + else + { + FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_TPM_NUM_FORMAT_ARGS, ((FFformatarg[]){ + FF_FORMAT_ARG(result.version, "version"), + FF_FORMAT_ARG(result.interfaceType, "interface-type"), + })); + } + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.interfaceType); +} + +bool ffParseTPMCommandOptions(FFTPMOptions* options, const char* key, const char* value) +{ + const char* subKey = ffOptionTestPrefix(key, FF_TPM_MODULE_NAME); + if (!subKey) return false; + if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs)) + return true; + + return false; +} + +void ffParseTPMJsonObject(FFTPMOptions* options, yyjson_val* module) +{ + yyjson_val *key_, *val; + size_t idx, max; + yyjson_obj_foreach(module, idx, max, key_, val) + { + const char* key = yyjson_get_str(key_); + if(ffStrEqualsIgnCase(key, "type")) + continue; + + if (ffJsonConfigParseModuleArgs(key, val, &options->moduleArgs)) + continue; + + ffPrintError(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, "Unknown JSON key %s", key); + } +} + +void ffGenerateTPMJsonConfig(FFTPMOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + __attribute__((__cleanup__(ffDestroyTPMOptions))) FFTPMOptions defaultOptions; + ffInitTPMOptions(&defaultOptions); + + ffJsonConfigGenerateModuleArgsConfig(doc, module, &defaultOptions.moduleArgs, &options->moduleArgs); +} + +void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_mut_doc* doc, yyjson_mut_val* module) +{ + FFTPMResult result = { + .version = ffStrbufCreate(), + .interfaceType = ffStrbufCreate() + }; + const char* error = ffDetectTPM(&result); + + if(error) + { + yyjson_mut_obj_add_str(doc, module, "error", error); + return; + } + + yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); + yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); + yyjson_mut_obj_add_strbuf(doc, obj, "interfaceType", &result.interfaceType); + + ffStrbufDestroy(&result.version); + ffStrbufDestroy(&result.interfaceType); +} + +void ffPrintTPMHelpFormat(void) +{ + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_TPM_MODULE_NAME, "{1} [{2}]", FF_TPM_NUM_FORMAT_ARGS, ((const char* []) { + "TPM device version - version", + "TPM interface type - interface-type", + })); +} + +void ffInitTPMOptions(FFTPMOptions* options) +{ + ffOptionInitModuleBaseInfo( + &options->moduleInfo, + FF_TPM_MODULE_NAME, + "Print info of Trusted Platform Module (TPM) Security Device", + ffParseTPMCommandOptions, + ffParseTPMJsonObject, + ffPrintTPM, + ffGenerateTPMJsonResult, + ffPrintTPMHelpFormat, + ffGenerateTPMJsonConfig + ); + ffOptionInitModuleArg(&options->moduleArgs, "󰔎"); +} + +void ffDestroyTPMOptions(FFTPMOptions* options) +{ + ffOptionDestroyModuleArg(&options->moduleArgs); +} diff --git a/src/modules/tpm/tpm.h b/src/modules/tpm/tpm.h new file mode 100644 index 000000000..3356a46dc --- /dev/null +++ b/src/modules/tpm/tpm.h @@ -0,0 +1,9 @@ +#pragma once + +#include "fastfetch.h" + +#define FF_TPM_MODULE_NAME "TPM" + +void ffPrintTPM(FFTPMOptions* options); +void ffInitTPMOptions(FFTPMOptions* options); +void ffDestroyTPMOptions(FFTPMOptions* options); diff --git a/src/options/modules.c b/src/options/modules.c index 10b6fc627..cea3c7af0 100644 --- a/src/options/modules.c +++ b/src/options/modules.c @@ -63,6 +63,7 @@ void ffOptionsInitModules(FFOptionsModules* options) ffInitTerminalThemeOptions(&options->terminalTheme); ffInitThemeOptions(&options->theme); ffInitTitleOptions(&options->title); + ffInitTPMOptions(&options->tpm); ffInitUptimeOptions(&options->uptime); ffInitUsersOptions(&options->users); ffInitVersionOptions(&options->version); @@ -137,6 +138,7 @@ void ffOptionsDestroyModules(FFOptionsModules* options) ffDestroyTerminalThemeOptions(&options->terminalTheme); ffDestroyThemeOptions(&options->theme); ffDestroyTitleOptions(&options->title); + ffDestroyTPMOptions(&options->tpm); ffDestroyUptimeOptions(&options->uptime); ffDestroyUsersOptions(&options->users); ffDestroyVersionOptions(&options->version); diff --git a/src/options/modules.h b/src/options/modules.h index 7f210be69..919d92408 100644 --- a/src/options/modules.h +++ b/src/options/modules.h @@ -64,6 +64,7 @@ typedef struct FFOptionsModules FFTerminalThemeOptions terminalTheme; FFThemeOptions theme; FFTitleOptions title; + FFTPMOptions tpm; FFUptimeOptions uptime; FFUsersOptions users; FFVersionOptions version; From 87f2e6916235006c950a1ec8c09b34232e3529a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 09:53:00 +0800 Subject: [PATCH 34/65] TPM: update description --- src/detection/tpm/tpm.h | 2 +- src/detection/tpm/tpm_linux.c | 20 +++++++++++--------- src/detection/tpm/tpm_windows.c | 10 +++++----- src/modules/tpm/tpm.c | 23 +++++++++++++---------- 4 files changed, 30 insertions(+), 25 deletions(-) diff --git a/src/detection/tpm/tpm.h b/src/detection/tpm/tpm.h index d8bc72b54..2310a23bf 100644 --- a/src/detection/tpm/tpm.h +++ b/src/detection/tpm/tpm.h @@ -5,7 +5,7 @@ typedef struct FFTPMResult { FFstrbuf version; - FFstrbuf interfaceType; + FFstrbuf description; } FFTPMResult; const char* ffDetectTPM(FFTPMResult* result); diff --git a/src/detection/tpm/tpm_linux.c b/src/detection/tpm/tpm_linux.c index 14e8be369..2547339c6 100644 --- a/src/detection/tpm/tpm_linux.c +++ b/src/detection/tpm/tpm_linux.c @@ -1,22 +1,24 @@ #include "tpm.h" #include "common/io/io.h" -const char* ffDetectTPM(FF_MAYBE_UNUSED FFTPMResult* result) +const char* ffDetectTPM(FFTPMResult* result) { + if (!ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) + { + if (!ffPathExists("/sys/class/tpm", FF_PATHTYPE_DIRECTORY)) + return "TPM is not supported by kernel"; + return "TPM device is not found"; + } + if (ffReadFileBuffer("/sys/class/tpm/tpm0/tpm_version_major", &result->version)) { ffStrbufTrimRightSpace(&result->version); if (ffStrbufEqualS(&result->version, "2")) ffStrbufSetStatic(&result->version, "2.0"); - - return NULL; } - if (ffPathExists("/sys/class/tpm/tpm0", FF_PATHTYPE_DIRECTORY)) - { - ffStrbufSetStatic(&result->version, "unknown"); - return NULL; - } + if (ffReadFileBuffer("/sys/class/tpm/tpm0/device/description", &result->description)) + ffStrbufTrimRightSpace(&result->description); - return "TPM device is not found"; + return NULL; } diff --git a/src/detection/tpm/tpm_windows.c b/src/detection/tpm/tpm_windows.c index 2837822d8..a63a93f5f 100644 --- a/src/detection/tpm/tpm_windows.c +++ b/src/detection/tpm/tpm_windows.c @@ -60,19 +60,19 @@ const char* ffDetectTPM(FFTPMResult* result) switch (deviceInfo.tpmInterfaceType) { case TPM_IFTYPE_1: - ffStrbufSetStatic(&result->interfaceType, "I/O-port or MMIO"); + ffStrbufSetF(&result->description, "I/O-port or MMIO TPM %s", result->version.chars); break; case TPM_IFTYPE_TRUSTZONE: - ffStrbufSetStatic(&result->interfaceType, "Trustzone"); + ffStrbufSetF(&result->description, "Trustzone TPM %s", result->version.chars); break; case TPM_IFTYPE_HW: - ffStrbufSetStatic(&result->interfaceType, "HW TPM"); + ffStrbufSetF(&result->description, "HW TPM %s", result->version.chars); break; case TPM_IFTYPE_EMULATOR: - ffStrbufSetStatic(&result->interfaceType, "SW-emulator"); + ffStrbufSetF(&result->description, "SW-emulator TPM %s", result->version.chars); break; case TPM_IFTYPE_SPB: - ffStrbufSetStatic(&result->interfaceType, "SPB attached"); + ffStrbufSetF(&result->description, "SPB attached TPM %s", result->version.chars); break; default: break; diff --git a/src/modules/tpm/tpm.c b/src/modules/tpm/tpm.c index f9b7a1e5d..3934fb4ce 100644 --- a/src/modules/tpm/tpm.c +++ b/src/modules/tpm/tpm.c @@ -10,7 +10,7 @@ void ffPrintTPM(FFTPMOptions* options) { FFTPMResult result = { .version = ffStrbufCreate(), - .interfaceType = ffStrbufCreate() + .description = ffStrbufCreate() }; const char* error = ffDetectTPM(&result); @@ -23,18 +23,21 @@ void ffPrintTPM(FFTPMOptions* options) if(options->moduleArgs.outputFormat.length == 0) { ffPrintLogoAndKey(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT); - ffStrbufPutTo(&result.version, stdout); + if (result.description.length > 0) + ffStrbufPutTo(&result.description, stdout); + else + ffStrbufPutTo(&result.version, stdout); } else { FF_PRINT_FORMAT_CHECKED(FF_TPM_MODULE_NAME, 0, &options->moduleArgs, FF_PRINT_TYPE_DEFAULT, FF_TPM_NUM_FORMAT_ARGS, ((FFformatarg[]){ FF_FORMAT_ARG(result.version, "version"), - FF_FORMAT_ARG(result.interfaceType, "interface-type"), + FF_FORMAT_ARG(result.description, "description"), })); } ffStrbufDestroy(&result.version); - ffStrbufDestroy(&result.interfaceType); + ffStrbufDestroy(&result.description); } bool ffParseTPMCommandOptions(FFTPMOptions* options, const char* key, const char* value) @@ -76,7 +79,7 @@ void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_ { FFTPMResult result = { .version = ffStrbufCreate(), - .interfaceType = ffStrbufCreate() + .description = ffStrbufCreate() }; const char* error = ffDetectTPM(&result); @@ -88,17 +91,17 @@ void ffGenerateTPMJsonResult(FF_MAYBE_UNUSED FFTerminalOptions* options, yyjson_ yyjson_mut_val* obj = yyjson_mut_obj_add_obj(doc, module, "result"); yyjson_mut_obj_add_strbuf(doc, obj, "version", &result.version); - yyjson_mut_obj_add_strbuf(doc, obj, "interfaceType", &result.interfaceType); + yyjson_mut_obj_add_strbuf(doc, obj, "description", &result.description); ffStrbufDestroy(&result.version); - ffStrbufDestroy(&result.interfaceType); + ffStrbufDestroy(&result.description); } void ffPrintTPMHelpFormat(void) { - FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_TPM_MODULE_NAME, "{1} [{2}]", FF_TPM_NUM_FORMAT_ARGS, ((const char* []) { + FF_PRINT_MODULE_FORMAT_HELP_CHECKED(FF_TPM_MODULE_NAME, "{2}", FF_TPM_NUM_FORMAT_ARGS, ((const char* []) { "TPM device version - version", - "TPM interface type - interface-type", + "TPM general description - description", })); } @@ -115,7 +118,7 @@ void ffInitTPMOptions(FFTPMOptions* options) ffPrintTPMHelpFormat, ffGenerateTPMJsonConfig ); - ffOptionInitModuleArg(&options->moduleArgs, "󰔎"); + ffOptionInitModuleArg(&options->moduleArgs, ""); } void ffDestroyTPMOptions(FFTPMOptions* options) From 8295f66320728efe85bd49cde8fd78201e563a0f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 10:39:03 +0800 Subject: [PATCH 35/65] TPM (FreeBSD): add support --- CMakeLists.txt | 2 +- src/detection/tpm/tpm_bsd.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/detection/tpm/tpm_bsd.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 46c656957..c959e5ab3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -641,7 +641,7 @@ elseif(FreeBSD) src/detection/terminalshell/terminalshell_linux.c src/detection/terminalsize/terminalsize_linux.c src/detection/theme/theme_linux.c - src/detection/tpm/tpm_nosupport.c + src/detection/tpm/tpm_bsd.c src/detection/uptime/uptime_bsd.c src/detection/users/users_linux.c src/detection/wallpaper/wallpaper_linux.c diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c new file mode 100644 index 000000000..ffaf0009b --- /dev/null +++ b/src/detection/tpm/tpm_bsd.c @@ -0,0 +1,17 @@ +#include "tpm.h" +#include "common/sysctl.h" + +const char* ffDetectTPM(FFTPMResult* result) +{ + if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) + return "TPM device is not found or TPM kernel module is not loaded"; + + if (ffStrbufContainS(&result->description, "2.0")) + ffStrbufSetStatic(&result->version, "2.0"); + else if (ffStrbufContainS(&result->description, "1.2")) + ffStrbufSetStatic(&result->version, "1.2"); + else + ffStrbufSetStatic(&result->version, "unknown"); + + return "Not supported on this platform"; +} From 4d7d367e72c842bfaebfb372f3bd90472af53149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 14:34:51 +0800 Subject: [PATCH 36/65] FFstrbuf: add new methods `ffStrbufPrependC` and `ffStrbufInsertNC` --- src/util/FFstrbuf.c | 20 ++++++++++++++++++++ src/util/FFstrbuf.h | 3 +++ tests/strbuf.c | 26 ++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/util/FFstrbuf.c b/src/util/FFstrbuf.c index c4a01592e..4387a5d7b 100644 --- a/src/util/FFstrbuf.c +++ b/src/util/FFstrbuf.c @@ -211,6 +211,14 @@ void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value) strbuf->length += length; } +void ffStrbufPrependC(FFstrbuf* strbuf, char c) +{ + ffStrbufEnsureFree(strbuf, 1); + memmove(strbuf->chars + 1, strbuf->chars, strbuf->length + 1); // + 1 for the null byte + strbuf->chars[0] = c; + strbuf->length += 1; +} + void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value) { ffStrbufClear(strbuf); @@ -511,3 +519,15 @@ void ffStrbufLowerCase(FFstrbuf* strbuf) for (uint32_t i = 0; i < strbuf->length; ++i) strbuf->chars[i] = (char) tolower(strbuf->chars[i]); } + +void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c) +{ + if(num == 0) return; + if (index >= strbuf->length) + index = strbuf->length; + + ffStrbufEnsureFree(strbuf, num); + memmove(strbuf->chars + index + num, strbuf->chars + index, strbuf->length - index + 1); + memset(&strbuf->chars[index], c, num); + strbuf->length += num; +} diff --git a/src/util/FFstrbuf.h b/src/util/FFstrbuf.h index a3b7179a4..a79ba2cc1 100644 --- a/src/util/FFstrbuf.h +++ b/src/util/FFstrbuf.h @@ -47,6 +47,9 @@ void ffStrbufAppendVF(FFstrbuf* strbuf, const char* format, va_list arguments); const char* ffStrbufAppendSUntilC(FFstrbuf* strbuf, const char* value, char until); void ffStrbufPrependNS(FFstrbuf* strbuf, uint32_t length, const char* value); +void ffStrbufPrependC(FFstrbuf* strbuf, char c); + +void ffStrbufInsertNC(FFstrbuf* strbuf, uint32_t index, uint32_t num, char c); void ffStrbufSetNS(FFstrbuf* strbuf, uint32_t length, const char* value); void ffStrbufSet(FFstrbuf* strbuf, const FFstrbuf* value); diff --git a/tests/strbuf.c b/tests/strbuf.c index 01db4e094..d901faab1 100644 --- a/tests/strbuf.c +++ b/tests/strbuf.c @@ -279,6 +279,20 @@ int main(void) VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST")); VERIFY(strbuf.length == 9); VERIFY(strbuf.allocated >= 10); + ffStrbufAppendC(&strbuf, '_'); + VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST_")); + ffStrbufDestroy(&strbuf); + VERIFY(strbuf.length == 0); + VERIFY(strbuf.allocated == 0); + + //ffStrbufCreateStatic / Prepend + ffStrbufInitStatic(&strbuf, "TEST"); + ffStrbufPrependS(&strbuf, "TEST_"); + VERIFY(ffStrbufEqualS(&strbuf, "TEST_TEST")); + VERIFY(strbuf.length == 9); + VERIFY(strbuf.allocated >= 10); + ffStrbufPrependC(&strbuf, '_'); + VERIFY(ffStrbufEqualS(&strbuf, "_TEST_TEST")); ffStrbufDestroy(&strbuf); VERIFY(strbuf.length == 0); VERIFY(strbuf.allocated == 0); @@ -416,6 +430,18 @@ int main(void) VERIFY(ffStrbufEqualS(&strbuf, "__TEST__")); ffStrbufDestroy(&strbuf); + //ffStrbufInsertNC + ffStrbufInitStatic(&strbuf, "123456"); + ffStrbufInsertNC(&strbuf, 0, 2, 'A'); + VERIFY(ffStrbufEqualS(&strbuf, "AA123456")); + ffStrbufInsertNC(&strbuf, 4, 2, 'B'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456")); + ffStrbufInsertNC(&strbuf, strbuf.length, 2, 'C'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456CC")); + ffStrbufInsertNC(&strbuf, 999, 2, 'D'); + VERIFY(ffStrbufEqualS(&strbuf, "AA12BB3456CCDD")); + ffStrbufDestroy(&strbuf); + //Success puts("\e[32mAll tests passed!" FASTFETCH_TEXT_MODIFIER_RESET); } From 28c9b674149bd8f0d5106a73fdbce57a6b1f2558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 14:41:06 +0800 Subject: [PATCH 37/65] Processing (Windows): correctly escaping arguments --- src/common/processing_windows.c | 45 ++++++++++++++++++++++++++++----- src/data/help.json | 2 +- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/common/processing_windows.c b/src/common/processing_windows.c index 03fb7cbfd..c2d2b10fa 100644 --- a/src/common/processing_windows.c +++ b/src/common/processing_windows.c @@ -8,6 +8,43 @@ enum { FF_PIPE_BUFSIZ = 8192 }; +static void argvToCmdline(char* const argv[], FFstrbuf* result) +{ + // From https://gist.github.com/jin-x/cdd641d98887524b091fb1f82a68717d + + FF_STRBUF_AUTO_DESTROY temp = ffStrbufCreate(); + for (int i = 0; argv[i] != NULL; i++) + { + ffStrbufSetS(&temp, argv[i]); + // Add slash (\) before double quotes (") and duplicate slashes before it + for ( + uint32_t pos = ffStrbufFirstIndexC(&temp, '"'), cnt; + pos != temp.length; + pos = ffStrbufNextIndexC(&temp, pos + cnt * 2, '"') + ) { + cnt = 1; + while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; } + ffStrbufInsertNC(&temp, pos, cnt, '\\'); + } + + // Add quotes around string if whitespace chars are present (with slash duplicating at the end of string) + if (ffStrbufFirstIndexS(&temp, " \t") != temp.length) + { + uint32_t pos = temp.length; + uint32_t cnt = 0; + while (pos > 0 && temp.chars[pos - 1] == '\\') { ++cnt, --pos; } + if (cnt > 0) ffStrbufAppendNC(&temp, cnt, '\\'); + ffStrbufPrependC(&temp, '"'); + ffStrbufAppendC(&temp, '"'); + } + + // Add space delimiter + if (i > 0) ffStrbufAppendC(result, ' '); + ffStrbufAppend(result, &temp); + ffStrbufClear(&temp); + } +} + const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool useStdErr) { int timeout = instance.config.general.processingTimeout; @@ -55,12 +92,8 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use else siStartInfo.hStdOutput = hChildPipeWrite; - FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreateF("\"%s\"", argv[0]); - for(char* const* parg = &argv[1]; *parg; ++parg) - { - ffStrbufAppendC(&cmdline, ' '); - ffStrbufAppendS(&cmdline, *parg); - } + FF_STRBUF_AUTO_DESTROY cmdline = ffStrbufCreate(); + argvToCmdline(argv, &cmdline); success = CreateProcessA( NULL, // application name diff --git a/src/data/help.json b/src/data/help.json index 486c6c61f..0d3424adb 100644 --- a/src/data/help.json +++ b/src/data/help.json @@ -1379,7 +1379,7 @@ { "long": "command-param", "desc": "Set the parameter used when starting the shell", - "remark": "Due to the difference of how OSes handle command line parameters, Windows will parse whitespaces as param separators, while *nix will not", + "remark": "If set to empty string, it will be ignored", "arg": { "type": "str", "default": "\"/c\" for Windows; \"-c\" for *nix" From b37b495aee0dc05d311ba17985e8ccfa8fe43c00 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 14:58:26 +0800 Subject: [PATCH 38/65] TPM (FreeBSD): report clearer error if tpm module is not loaded --- src/detection/tpm/tpm_bsd.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c index ffaf0009b..f51adb8ad 100644 --- a/src/detection/tpm/tpm_bsd.c +++ b/src/detection/tpm/tpm_bsd.c @@ -1,10 +1,16 @@ #include "tpm.h" #include "common/sysctl.h" +#include +#include + const char* ffDetectTPM(FFTPMResult* result) { if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) - return "TPM device is not found or TPM kernel module is not loaded"; + { + if (modfind("tpm") < 0) return "TPM kernel module is not loaded"; + return "TPM device is not found"; + } if (ffStrbufContainS(&result->description, "2.0")) ffStrbufSetStatic(&result->version, "2.0"); From 01735d6fdeba6ec1f3d19150420c24b6980edef8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 15:02:43 +0800 Subject: [PATCH 39/65] Presets: add tpm to all & ci --- presets/all.jsonc | 1 + presets/ci.jsonc | 1 + 2 files changed, 2 insertions(+) diff --git a/presets/all.jsonc b/presets/all.jsonc index b1c28c31d..9b27615e0 100644 --- a/presets/all.jsonc +++ b/presets/all.jsonc @@ -97,6 +97,7 @@ "type": "physicaldisk", "temp": true }, + "tpm", "version", "break", "colors" diff --git a/presets/ci.jsonc b/presets/ci.jsonc index 2bb446bfd..3027010d8 100644 --- a/presets/ci.jsonc +++ b/presets/ci.jsonc @@ -99,6 +99,7 @@ "type": "physicaldisk", "temp": true }, + "tpm", "version", "break", "colors" From e3cb52583d894be5d3eed5aa82ac39bb5eabaf29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 15:08:59 +0800 Subject: [PATCH 40/65] CI: try building with `-DENABLE_EMBEDDED_PCIIDS=ON` --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 461d96127..e198fe29d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -87,7 +87,7 @@ jobs: languages: c - name: configure project - run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . + run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DCMAKE_INSTALL_PREFIX=/usr . - name: build project run: cmake --build . --target package --verbose -j4 @@ -252,7 +252,7 @@ jobs: - name: build run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -GNinja . + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr -DIS_MUSL=ON -DENABLE_EMBEDDED_PCIIDS=On -GNinja . cmake --build . --target package --verbose -j4 shell: alpine.sh {0} @@ -385,7 +385,7 @@ jobs: pkg install gcc13 cmake git pkg-config glib2 dbus sqlite-3 imagemagick run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -423,7 +423,7 @@ jobs: uname -a sudo pkg update sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false From fc05d728f3a46a5101c8c78e2862439f49921b0f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 16:05:34 +0800 Subject: [PATCH 41/65] Util: add function `ffKernelModLoaded` and use it --- CMakeLists.txt | 1 + src/detection/tpm/tpm_bsd.c | 6 ++--- src/detection/zpool/zpool_linux.c | 7 +++++- src/util/kernelMod.c | 39 +++++++++++++++++++++++++++++++ src/util/kernelMod.h | 5 ++++ 5 files changed, 53 insertions(+), 5 deletions(-) create mode 100644 src/util/kernelMod.c create mode 100644 src/util/kernelMod.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c959e5ab3..634a99d08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -424,6 +424,7 @@ set(LIBFASTFETCH_SRC src/util/base64.c src/util/FFlist.c src/util/FFstrbuf.c + src/util/kernelMod.c src/util/path.c src/util/platform/FFPlatform.c src/util/smbiosHelper.c diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c index f51adb8ad..53dbba539 100644 --- a/src/detection/tpm/tpm_bsd.c +++ b/src/detection/tpm/tpm_bsd.c @@ -1,14 +1,12 @@ #include "tpm.h" #include "common/sysctl.h" - -#include -#include +#include "util/kernelMod.h" const char* ffDetectTPM(FFTPMResult* result) { if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) { - if (modfind("tpm") < 0) return "TPM kernel module is not loaded"; + if (ffKernelModLoaded("tpm")) return "`tpm` kernel module is not loaded"; return "TPM device is not found"; } diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index c183c3785..dcbdbfd90 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -1,6 +1,7 @@ #include "zpool.h" #ifdef FF_HAVE_LIBZFS +#include "util/kernelMod.h" #ifdef __sun #define FF_DISABLE_DLOPEN @@ -82,7 +83,11 @@ const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libzfs, libzfs_init); libzfs_handle_t* handle = fflibzfs_init(); - if (!handle) return "libzfs_init() failed"; + if (!handle) + { + if (!ffKernelModLoaded("zfs")) return "`zfs` kernel module is not loaded"; + return "libzfs_init() failed"; + } __attribute__((__cleanup__(cleanLibzfs))) FFZfsData data = { .handle = handle, diff --git a/src/util/kernelMod.c b/src/util/kernelMod.c new file mode 100644 index 000000000..94e11ec70 --- /dev/null +++ b/src/util/kernelMod.c @@ -0,0 +1,39 @@ +#include "kernelMod.h" + +#if __linux__ +#include "common/io/io.h" + +bool ffKernelModLoaded(const char* modName) +{ + static FFstrbuf modules; + if (modules.chars == NULL) + { + ffStrbufInitS(&modules, "\n"); + ffAppendFileBuffer("/proc/modules", &modules); + } + + if (modules.length == 0) return false; + + uint32_t len = (uint32_t) strlen(modName); + if (len > 250) return false; + + char temp[256]; + temp[0] = '\n'; + memcpy(temp + 1, modName, len); + temp[1 + len] = ' '; + return memmem(modules.chars, modules.length, temp, len + 2) != NULL; +} +#elif __FreeBSD__ +#include +#include + +bool ffKernelModLoaded(const char* modName) +{ + return modfind(modName) >= 0; +} +#else +bool ffKernelModLoaded(FF_MAYBE_UNUSED const char* modName) +{ + return true; // Don't generate kernel module related errors +} +#endif diff --git a/src/util/kernelMod.h b/src/util/kernelMod.h new file mode 100644 index 000000000..74f6f9292 --- /dev/null +++ b/src/util/kernelMod.h @@ -0,0 +1,5 @@ +#pragma once + +#include "fastfetch.h" + +bool ffKernelModLoaded(const char* modName); From af63e6e98b834c275fcca0bd7bdd86276a71b174 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 16:43:54 +0800 Subject: [PATCH 42/65] GPU (macOS): detect GPU driver version --- src/detection/gpu/gpu_apple.c | 3 +++ src/detection/gpu/gpu_apple.m | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/detection/gpu/gpu_apple.c b/src/detection/gpu/gpu_apple.c index 5abf00409..16f9f9c0c 100644 --- a/src/detection/gpu/gpu_apple.c +++ b/src/detection/gpu/gpu_apple.c @@ -7,6 +7,7 @@ #include const char* ffGpuDetectMetal(FFlist* gpus); +const char* ffGpuDetectDriverVersion(FFlist* gpus); static double detectGpuTemp(const FFstrbuf* gpuName) { @@ -185,5 +186,7 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) } ffGpuDetectMetal(gpus); + if (instance.config.general.detectVersion) + ffGpuDetectDriverVersion(gpus); return NULL; } diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index aead1c217..3719760fd 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -1,6 +1,7 @@ #include "gpu.h" #import +#import #ifndef MAC_OS_VERSION_13_0 #define MTLGPUFamilyMetal3 ((MTLGPUFamily) 5001) @@ -10,6 +11,28 @@ #define MTLFeatureSet_macOS_GPUFamily2_v1 ((MTLFeatureSet) 10005) #endif +const char* ffGpuDetectDriverVersion(FFlist* gpus) +{ + if (@available(macOS 10.7, *)) + { + NSMutableArray* arr = NSMutableArray.new; + FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) + [arr addObject:@(x->driver.chars)]; + + NSDictionary* dict = CFBridgingRelease(KextManagerCopyLoadedKextInfo((__bridge CFArrayRef)arr, (__bridge CFArrayRef)@[@"CFBundleVersion"])); + FF_LIST_FOR_EACH(FFGPUResult, x, *gpus) + { + NSString* version = dict[@(x->driver.chars)][@"CFBundleVersion"]; + if (version) + { + ffStrbufAppendC(&x->driver, ' '); + ffStrbufAppendS(&x->driver, version.UTF8String); + } + } + } + return "Unsupported macOS version"; +} + const char* ffGpuDetectMetal(FFlist* gpus) { if (@available(macOS 10.13, *)) From d095f394180bedd6c35beef95441c220a28827f5 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 19:23:21 +0800 Subject: [PATCH 43/65] TPM (FreeBSD): fix silly bug... --- src/detection/tpm/tpm_bsd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c index 53dbba539..7ee11cbea 100644 --- a/src/detection/tpm/tpm_bsd.c +++ b/src/detection/tpm/tpm_bsd.c @@ -6,7 +6,7 @@ const char* ffDetectTPM(FFTPMResult* result) { if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) { - if (ffKernelModLoaded("tpm")) return "`tpm` kernel module is not loaded"; + if (!ffKernelModLoaded("tpm")) return "`tpm` kernel module is not loaded"; return "TPM device is not found"; } @@ -17,5 +17,5 @@ const char* ffDetectTPM(FFTPMResult* result) else ffStrbufSetStatic(&result->version, "unknown"); - return "Not supported on this platform"; + return NULL; } From e07fcc4d492e9b87020cb01fad9f6e31d9fb1eab Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 19:37:24 +0800 Subject: [PATCH 44/65] Scripts: fix old python version compatibility --- scripts/gen-pciids.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py index bc98fec55..20ffbaf58 100644 --- a/scripts/gen-pciids.py +++ b/scripts/gen-pciids.py @@ -55,17 +55,19 @@ typedef struct FFPciVendor for vendor in vendors: if vendor.devices: + piece = ',\n '.join('{{ 0x{:04X}, "{}" }}'.format(device.id, device.name.replace('"', '\\"')) for device in vendor.devices) code += f""" // {vendor.name} static const FFPciDevice pciDevices_{vendor.id:04X}[] = {{ - {',\n '.join(f'{{ 0x{device.id:04X}, "{device.name.replace('"', '\\"')}" }}' for device in vendor.devices)}, + {piece}, {{}}, }}; """ + piece = ',\n '.join('{{ 0x{:04X}, "{}", {}, {} }}'.format(vendor.id, vendor.name.replace('"', '\\"'), vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL", len(vendor.devices)) for vendor in vendors) code += f""" const FFPciVendor ffPciVendors[] = {{ - {',\n '.join(f'{{ 0x{vendor.id:04X}, "{vendor.name.replace('"', '\\"')}", {vendor.devices and f"pciDevices_{vendor.id:04X}" or "NULL"}, {len(vendor.devices)} }}' for vendor in vendors)}, + {piece}, {{}}, }};""" From 4283d96c538d50f2e8c8d05f3292ecb8d64af647 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Thu, 26 Sep 2024 19:56:36 +0800 Subject: [PATCH 45/65] CI: fix build --- .github/workflows/ci.yml | 8 ++++---- scripts/gen-pciids.py | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e198fe29d..a2bdf2701 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: run: uname -a - name: install required packages - run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev + run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev libosmesa6-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev python3-requests - name: install linuxbrew packages run: | @@ -247,7 +247,7 @@ jobs: run: | cat /etc/alpine-release uname -a - apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev gcc g++ + apk add cmake samurai vulkan-loader-dev libxcb-dev wayland-dev libdrm-dev dconf-dev imagemagick-dev chafa-dev zlib-dev dbus-dev mesa-dev opencl-dev xfconf-dev sqlite-dev networkmanager-dev pulseaudio-dev ddcutil-dev elfutils-dev py3-requests gcc g++ shell: alpine.sh --root {0} - name: build @@ -385,7 +385,7 @@ jobs: pkg install gcc13 cmake git pkg-config glib2 dbus sqlite-3 imagemagick run: | - cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On . + cmake -DSET_TWEAK=Off -DBUILD_TESTS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features time ./fastfetch -c presets/ci.jsonc --stat false @@ -422,7 +422,7 @@ jobs: run: | uname -a sudo pkg update - sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat + sudo pkg install -y cmake git pkgconf binutils wayland vulkan-headers vulkan-loader libxcb libXrandr libX11 libdrm libelf glib dconf dbus sqlite3-tcl xfce4-conf egl libosmesa opencl ocl-icd v4l_compat py311-requests cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On . cmake --build . --target package --verbose -j4 ./fastfetch --list-features diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py index 20ffbaf58..6c30fb735 100644 --- a/scripts/gen-pciids.py +++ b/scripts/gen-pciids.py @@ -9,10 +9,10 @@ class PciVendorModel: def __init__(self, id: int, name: str): self.id = id self.name = name - self.devices: list[PciDeviceModel] = [] + self.devices = [] -def main(keep_vendor_list: set[int]): - vendors: list[PciVendorModel] = [] +def main(keep_vendor_list: set): + vendors = [] try: with open('pci.ids', 'r') as f: full_text = f.read() From 745c041b441bfadf4781d02f90a1a7d67d8983eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Thu, 26 Sep 2024 23:53:13 +0800 Subject: [PATCH 46/65] GPU (Linux): fix some obvious bugs found in #1284 --- src/detection/gpu/gpu_linux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 0db1373a7..6472f36a2 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -99,7 +99,7 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult if (options->temp) { if (ffamdgpu_query_sensor_info(handle, AMDGPU_INFO_SENSOR_GPU_TEMP, sizeof(value), &value) >= 0) - gpu->temperature = value; + gpu->temperature = value / 1000.; } ffStrbufSetS(&gpu->name, ffamdgpu_get_marketing_name(handle)); @@ -107,9 +107,9 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult struct amdgpu_gpu_info gpuInfo; if (ffamdgpu_query_gpu_info(handle, &gpuInfo) >= 0) { - gpu->coreCount = (int32_t) gpuInfo.num_shader_engines; + gpu->coreCount = (int32_t) gpuInfo.cu_active_number; gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u); - gpu->index = gpuInfo.asic_id; + gpu->index = FF_GPU_INDEX_UNSET; gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; struct amdgpu_heap_info heapInfo; From 78fc5a2b5d607e38e49230eae4addbcb38bc6625 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 00:00:04 +0800 Subject: [PATCH 47/65] GPU: fix compiling error when `-DCUSTOM_PCI_IDS_PATH` is used --- src/detection/gpu/gpu_pci.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index 5aa86a7b8..558a7722c 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -10,6 +10,9 @@ #include "fastfetch_pciids.c.inc" #endif +#define FF_STR_INDIR(x) #x +#define FF_STR(x) FF_STR_INDIR(x) + static const FFstrbuf* loadPciIds() { static FFstrbuf pciids; @@ -19,7 +22,7 @@ static const FFstrbuf* loadPciIds() #ifdef FF_CUSTOM_PCI_IDS_PATH - ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), pciids); + ffReadFileBuffer(FF_STR(FF_CUSTOM_PCI_IDS_PATH), &pciids); #else // FF_CUSTOM_PCI_IDS_PATH From 254876b9e6f50b3c54e22851bba8d264d98d4fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 00:12:52 +0800 Subject: [PATCH 48/65] GPU (Linux): try fixing linking errors when dyamic linking is used Fix #1295 --- .github/workflows/ci.yml | 2 +- CMakeLists.txt | 5 +++++ src/common/init.c | 3 +++ src/detection/gpu/gpu_linux.c | 7 ++++--- 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a2bdf2701..1745a789d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,7 @@ jobs: run: uname -a - name: configure project - run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF + run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DCMAKE_INSTALL_PREFIX=/usr . -DENABLE_VULKAN=OFF -DENABLE_WAYLAND=OFF -DENABLE_XCB_RANDR=OFF -DENABLE_XCB=OFF -DENABLE_XRANDR=OFF -DENABLE_X11=OFF -DENABLE_DRM=OFF -DENABLE_DRM_AMDGPU=OFF -DENABLE_GIO=OFF -DENABLE_DCONF=OFF -DENABLE_DBUS=OFF -DENABLE_XFCONF=OFF -DENABLE_SQLITE3=OFF -DENABLE_RPM=OFF -DENABLE_IMAGEMAGICK7=OFF -DENABLE_IMAGEMAGICK6=OFF -DENABLE_CHAFA=OFF -DENABLE_ZLIB=OFF -DENABLE_EGL=OFF -DENABLE_GLX=OFF -DENABLE_OSMESA=OFF -DENABLE_OPENCL=OFF -DENABLE_FREETYPE=OFF -DENABLE_PULSE=OFF -DENABLE_DDCUTIL=OFF -DENABLE_ELF=OFF -DENABLE_DIRECTX_HEADERS=OFF -DENABLE_THREADS=OFF - name: build project run: cmake --build . --target package --verbose -j4 diff --git a/CMakeLists.txt b/CMakeLists.txt index 634a99d08..340f0a520 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ cmake_dependent_option(ENABLE_XCB "Enable xcb" ON "LINUX OR FreeBSD OR SunOS" OF cmake_dependent_option(ENABLE_XRANDR "Enable xrandr" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_X11 "Enable x11" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DRM "Enable libdrm" ON "LINUX OR FreeBSD OR SunOS" OFF) +cmake_dependent_option(ENABLE_DRM_AMDGPU "Enable libdrm_amdgpu" ON "LINUX" OFF) cmake_dependent_option(ENABLE_GIO "Enable gio-2.0" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DCONF "Enable dconf" ON "LINUX OR FreeBSD OR SunOS" OFF) cmake_dependent_option(ENABLE_DBUS "Enable dbus-1" ON "LINUX OR FreeBSD OR SunOS" OFF) @@ -1054,6 +1055,10 @@ ff_lib_enable(DRM "libdrm" "Libdrm" ) +ff_lib_enable(DRM_AMDGPU + "libdrm_amdgpu" + "Libdrm_Amdgpu" +) ff_lib_enable(GIO "gio-2.0" "GIO" diff --git a/src/common/init.c b/src/common/init.c index 9845ff526..514b9fb6a 100644 --- a/src/common/init.c +++ b/src/common/init.c @@ -191,6 +191,9 @@ void ffListFeatures(void) #if FF_HAVE_DRM "drm\n" #endif + #if FF_HAVE_DRM_AMDGPU + "drm_amdgpu\n" + #endif #if FF_HAVE_GIO "gio\n" #endif diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 6472f36a2..35b50b9a8 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -9,7 +9,7 @@ #include -#ifdef FF_HAVE_DRM +#ifdef FF_HAVE_DRM_AMDGPU #include #include #include @@ -73,8 +73,8 @@ static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) { - #if FF_HAVE_DRM - FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 2) + #if FF_HAVE_DRM_AMDGPU + FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_gpu_info) @@ -135,6 +135,7 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult return NULL; #else + FF_UNUSED(options, gpu, drmKey, buffer); return "Fastfetch is compiled without libdrm support"; #endif } From 8bbc985d9819db23efed90823b281e212a6a116b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 00:19:07 +0800 Subject: [PATCH 49/65] CMake: fix more linking errors in dynamic mode --- CMakeLists.txt | 8 ++++++++ src/detection/gpu/gpu_mthreads.c | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 340f0a520..819e16402 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1169,6 +1169,14 @@ if(LINUX) target_link_libraries(libfastfetch PRIVATE "m" ) + + if(ENABLE_DIRECTX_HEADERS) + if(NOT BINARY_LINK_TYPE STREQUAL "dlopen") + target_link_libraries(libfastfetch + PRIVATE "/usr/lib/wsl/lib/libdxcore.so" + ) + endif() + endif() elseif(APPLE) target_link_libraries(libfastfetch PRIVATE "-framework AVFoundation" diff --git a/src/detection/gpu/gpu_mthreads.c b/src/detection/gpu/gpu_mthreads.c index 7af21c58f..80164320d 100644 --- a/src/detection/gpu/gpu_mthreads.c +++ b/src/detection/gpu/gpu_mthreads.c @@ -30,7 +30,7 @@ struct FFMtmlData MtmlSystem *sys; } mtmlData; -static void shutdownMtml() +FF_MAYBE_UNUSED static void shutdownMtml(void) { mtmlData.ffmtmlLibraryShutDown(mtmlData.lib); } From af067c7c3f3feb6d67ac385e7e9042677090335e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 08:36:38 +0800 Subject: [PATCH 50/65] Util: rename KernelMod to Kmod --- CMakeLists.txt | 2 +- src/detection/tpm/tpm_bsd.c | 4 ++-- src/detection/zpool/zpool_linux.c | 4 ++-- src/util/kernelMod.h | 5 ----- src/util/{kernelMod.c => kmod.c} | 8 ++++---- src/util/kmod.h | 5 +++++ 6 files changed, 14 insertions(+), 14 deletions(-) delete mode 100644 src/util/kernelMod.h rename src/util/{kernelMod.c => kmod.c} (80%) create mode 100644 src/util/kmod.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 819e16402..dd98838d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -425,7 +425,7 @@ set(LIBFASTFETCH_SRC src/util/base64.c src/util/FFlist.c src/util/FFstrbuf.c - src/util/kernelMod.c + src/util/kmod.c src/util/path.c src/util/platform/FFPlatform.c src/util/smbiosHelper.c diff --git a/src/detection/tpm/tpm_bsd.c b/src/detection/tpm/tpm_bsd.c index 7ee11cbea..2e32d512b 100644 --- a/src/detection/tpm/tpm_bsd.c +++ b/src/detection/tpm/tpm_bsd.c @@ -1,12 +1,12 @@ #include "tpm.h" #include "common/sysctl.h" -#include "util/kernelMod.h" +#include "util/kmod.h" const char* ffDetectTPM(FFTPMResult* result) { if (ffSysctlGetString("dev.tpmcrb.0.%desc", &result->description) != NULL) { - if (!ffKernelModLoaded("tpm")) return "`tpm` kernel module is not loaded"; + if (!ffKmodLoaded("tpm")) return "`tpm` kernel module is not loaded"; return "TPM device is not found"; } diff --git a/src/detection/zpool/zpool_linux.c b/src/detection/zpool/zpool_linux.c index dcbdbfd90..59890990b 100644 --- a/src/detection/zpool/zpool_linux.c +++ b/src/detection/zpool/zpool_linux.c @@ -1,7 +1,7 @@ #include "zpool.h" #ifdef FF_HAVE_LIBZFS -#include "util/kernelMod.h" +#include "util/kmod.h" #ifdef __sun #define FF_DISABLE_DLOPEN @@ -85,7 +85,7 @@ const char* ffDetectZpool(FFlist* result /* list of FFZpoolResult */) libzfs_handle_t* handle = fflibzfs_init(); if (!handle) { - if (!ffKernelModLoaded("zfs")) return "`zfs` kernel module is not loaded"; + if (!ffKmodLoaded("zfs")) return "`zfs` kernel module is not loaded"; return "libzfs_init() failed"; } diff --git a/src/util/kernelMod.h b/src/util/kernelMod.h deleted file mode 100644 index 74f6f9292..000000000 --- a/src/util/kernelMod.h +++ /dev/null @@ -1,5 +0,0 @@ -#pragma once - -#include "fastfetch.h" - -bool ffKernelModLoaded(const char* modName); diff --git a/src/util/kernelMod.c b/src/util/kmod.c similarity index 80% rename from src/util/kernelMod.c rename to src/util/kmod.c index 94e11ec70..c3579c95a 100644 --- a/src/util/kernelMod.c +++ b/src/util/kmod.c @@ -1,9 +1,9 @@ -#include "kernelMod.h" +#include "kmod.h" #if __linux__ #include "common/io/io.h" -bool ffKernelModLoaded(const char* modName) +bool ffKmodLoaded(const char* modName) { static FFstrbuf modules; if (modules.chars == NULL) @@ -27,12 +27,12 @@ bool ffKernelModLoaded(const char* modName) #include #include -bool ffKernelModLoaded(const char* modName) +bool ffKmodLoaded(const char* modName) { return modfind(modName) >= 0; } #else -bool ffKernelModLoaded(FF_MAYBE_UNUSED const char* modName) +bool ffKmodLoaded(FF_MAYBE_UNUSED const char* modName) { return true; // Don't generate kernel module related errors } diff --git a/src/util/kmod.h b/src/util/kmod.h new file mode 100644 index 000000000..013340b1a --- /dev/null +++ b/src/util/kmod.h @@ -0,0 +1,5 @@ +#pragma once + +#include "fastfetch.h" + +bool ffKmodLoaded(const char* modName); From a3a4f0a64aa825b27538eaaa1275342156e8080e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 09:02:00 +0800 Subject: [PATCH 51/65] Kmod: support macOS --- src/util/kmod.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/util/kmod.c b/src/util/kmod.c index c3579c95a..60d1889bf 100644 --- a/src/util/kmod.c +++ b/src/util/kmod.c @@ -31,6 +31,19 @@ bool ffKmodLoaded(const char* modName) { return modfind(modName) >= 0; } +#elif __APPLE__ +#include "util/apple/cf_helpers.h" +#include +#include + +bool ffKmodLoaded(const char* modName) +{ + FF_CFTYPE_AUTO_RELEASE CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, modName, kCFStringEncodingUTF8); + FF_CFTYPE_AUTO_RELEASE CFArrayRef identifiers = CFArrayCreate(kCFAllocatorDefault, (const void**) &name, 1, &kCFTypeArrayCallBacks); + FF_CFTYPE_AUTO_RELEASE CFArrayRef keys = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL); + FF_CFTYPE_AUTO_RELEASE CFDictionaryRef kextInfo = KextManagerCopyLoadedKextInfo(identifiers, keys); + return CFDictionaryContainsKey(kextInfo, name); +} #else bool ffKmodLoaded(FF_MAYBE_UNUSED const char* modName) { From 03565384e64957118f84855e5b282cfaa56e5107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 27 Sep 2024 09:16:54 +0800 Subject: [PATCH 52/65] Chore (macOS): use simplified syntax --- src/detection/cursor/cursor_apple.m | 14 +++++++------- src/detection/monitor/monitor_apple.m | 2 +- src/detection/os/os_apple.m | 6 +++--- src/detection/terminalfont/terminalfont_apple.m | 14 +++++++------- src/detection/wallpaper/wallpaper_apple.m | 8 ++++---- src/detection/wmtheme/wmtheme_apple.m | 4 ++-- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/detection/cursor/cursor_apple.m b/src/detection/cursor/cursor_apple.m index 40d4b90c9..29187e11d 100644 --- a/src/detection/cursor/cursor_apple.m +++ b/src/detection/cursor/cursor_apple.m @@ -4,10 +4,10 @@ static void appendColor(FFstrbuf* str, NSDictionary* color) { - int r = (int) (((NSNumber*) [color valueForKey:@"red"]).doubleValue * 255); - int g = (int) (((NSNumber*) [color valueForKey:@"green"]).doubleValue * 255); - int b = (int) (((NSNumber*) [color valueForKey:@"blue"]).doubleValue * 255); - int a = (int) (((NSNumber*) [color valueForKey:@"alpha"]).doubleValue * 255); + int r = (int) (((NSNumber*) color[@"red"]).doubleValue * 255); + int g = (int) (((NSNumber*) color[@"green"]).doubleValue * 255); + int b = (int) (((NSNumber*) color[@"blue"]).doubleValue * 255); + int a = (int) (((NSNumber*) color[@"alpha"]).doubleValue * 255); if (r == 255 && g == 255 && b == 255 && a == 255) ffStrbufAppendS(str, "White"); @@ -32,19 +32,19 @@ void ffDetectCursor(FFCursorResult* result) NSDictionary* color; ffStrbufAppendS(&result->theme, "Fill - "); - if ((color = [dict valueForKey:@"cursorFill"])) + if ((color = dict[@"cursorFill"])) appendColor(&result->theme, color); else ffStrbufAppendS(&result->theme, "Black"); ffStrbufAppendS(&result->theme, ", Outline - "); - if ((color = [dict valueForKey:@"cursorOutline"])) + if ((color = dict[@"cursorOutline"])) appendColor(&result->theme, color); else ffStrbufAppendS(&result->theme, "White"); - NSNumber* mouseDriverCursorSize = [dict valueForKey:@"mouseDriverCursorSize"]; + NSNumber* mouseDriverCursorSize = dict[@"mouseDriverCursorSize"]; if (mouseDriverCursorSize) ffStrbufAppendF(&result->size, "%d", (int) (mouseDriverCursorSize.doubleValue * 32)); else diff --git a/src/detection/monitor/monitor_apple.m b/src/detection/monitor/monitor_apple.m index 70d71eeb6..04163bc7c 100644 --- a/src/detection/monitor/monitor_apple.m +++ b/src/detection/monitor/monitor_apple.m @@ -29,7 +29,7 @@ static bool detectHdrSupportWithNSScreen(FFDisplayResult* display) for (NSScreen* screen in NSScreen.screens) { if (screen == mainScreen) continue; - NSNumber* screenNumber = [screen.deviceDescription valueForKey:@"NSScreenNumber"]; + NSNumber* screenNumber = screen.deviceDescription[@"NSScreenNumber"]; if (screenNumber && screenNumber.longValue == (long) display->id) { #ifdef MAC_OS_X_VERSION_10_15 diff --git a/src/detection/os/os_apple.m b/src/detection/os/os_apple.m index 5a8ef621a..b86202b1e 100644 --- a/src/detection/os/os_apple.m +++ b/src/detection/os/os_apple.m @@ -19,11 +19,11 @@ static void parseSystemVersion(FFOSResult* os) NSString* value; - if((value = [dict valueForKey:@"ProductName"])) + if((value = dict[@"ProductName"])) ffStrbufInitS(&os->name, value.UTF8String); - if((value = [dict valueForKey:@"ProductUserVisibleVersion"])) + if((value = dict[@"ProductUserVisibleVersion"])) ffStrbufInitS(&os->version, value.UTF8String); - if((value = [dict valueForKey:@"ProductBuildVersion"])) + if((value = dict[@"ProductBuildVersion"])) ffStrbufInitS(&os->buildID, value.UTF8String); } diff --git a/src/detection/terminalfont/terminalfont_apple.m b/src/detection/terminalfont/terminalfont_apple.m index 7d6aca282..90fed7fd1 100644 --- a/src/detection/terminalfont/terminalfont_apple.m +++ b/src/detection/terminalfont/terminalfont_apple.m @@ -26,12 +26,12 @@ static void detectIterm2(FFTerminalFontResult* terminalFont) return; } - for(NSDictionary* bookmark in [dict valueForKey:@"New Bookmarks"]) + for(NSDictionary* bookmark in dict[@"New Bookmarks"]) { - if(![[bookmark valueForKey:@"Name"] isEqualToString:@(profile)]) + if(![bookmark[@"Name"] isEqualToString:@(profile)]) continue; - NSString* normalFont = [bookmark valueForKey:@"Normal Font"]; + NSString* normalFont = bookmark[@"Normal Font"]; if(!normalFont) { ffStrbufAppendF(&terminalFont->error, "`Normal Font` key in profile `%s` doesn't exist", profile); @@ -39,10 +39,10 @@ static void detectIterm2(FFTerminalFontResult* terminalFont) } ffFontInitWithSpace(&terminalFont->font, normalFont.UTF8String); - NSNumber* useNonAsciiFont = [bookmark valueForKey:@"Use Non-ASCII Font"]; + NSNumber* useNonAsciiFont = bookmark[@"Use Non-ASCII Font"]; if(useNonAsciiFont.boolValue) { - NSString* nonAsciiFont = [bookmark valueForKey:@"Non Ascii Font"]; + NSString* nonAsciiFont = bookmark[@"Non Ascii Font"]; if (nonAsciiFont) ffFontInitWithSpace(&terminalFont->fallback, nonAsciiFont.UTF8String); } @@ -78,13 +78,13 @@ static void detectWarpTerminal(FFTerminalFontResult* terminalFont) return; } - NSString* fontName = [dict valueForKey:@"FontName"]; + NSString* fontName = dict[@"FontName"]; if(!fontName) fontName = @"Hack"; else fontName = [fontName stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\""]]; - NSString* fontSize = [dict valueForKey:@"FontSize"]; + NSString* fontSize = dict[@"FontSize"]; if(!fontSize) fontSize = @"13"; diff --git a/src/detection/wallpaper/wallpaper_apple.m b/src/detection/wallpaper/wallpaper_apple.m index eb330dda1..6780828d3 100644 --- a/src/detection/wallpaper/wallpaper_apple.m +++ b/src/detection/wallpaper/wallpaper_apple.m @@ -18,16 +18,16 @@ const char* ffDetectWallpaper(FFstrbuf* result) NSArray* choices = [dict valueForKeyPath:@"SystemDefault.Desktop.Content.Choices"]; if (choices.count > 0) { - NSDictionary* choice = [choices objectAtIndex:0]; - NSArray* files = [choice valueForKey:@"Files"]; + NSDictionary* choice = choices[0]; + NSArray* files = choice[@"Files"]; if (files.count > 0) { - NSString* file = [[files objectAtIndex: 0] valueForKey: @"relative"]; + NSString* file = files[0][@"relative"]; ffStrbufAppendS(result, [NSURL URLWithString:file].path.UTF8String); } else { - NSString* provider = [choice valueForKey:@"Provider"]; + NSString* provider = choice[@"Provider"]; NSString* builtinPrefix = @"com.apple.wallpaper.choice."; if ([provider hasPrefix:builtinPrefix]) provider = [provider substringFromIndex:builtinPrefix.length]; diff --git a/src/detection/wmtheme/wmtheme_apple.m b/src/detection/wmtheme/wmtheme_apple.m index 08810b6cc..8c43877b1 100644 --- a/src/detection/wmtheme/wmtheme_apple.m +++ b/src/detection/wmtheme/wmtheme_apple.m @@ -15,7 +15,7 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError) return false; } - NSNumber* wmThemeColor = [dict valueForKey:@"AppleAccentColor"]; + NSNumber* wmThemeColor = dict[@"AppleAccentColor"]; if(!wmThemeColor) ffStrbufAppendS(themeOrError, "Multicolor"); else @@ -34,7 +34,7 @@ bool ffDetectWmTheme(FFstrbuf* themeOrError) } } - NSString* wmTheme = [dict valueForKey:@"AppleInterfaceStyle"]; + NSString* wmTheme = dict[@"AppleInterfaceStyle"]; ffStrbufAppendF(themeOrError, " (%s)", wmTheme ? wmTheme.UTF8String : "Light"); return true; } From d6eff93c12a8982eb90beacd063f39d8c20b8f6f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 27 Sep 2024 09:54:22 +0800 Subject: [PATCH 53/65] GPU: fix usage of bsearch --- src/detection/gpu/gpu_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_pci.c b/src/detection/gpu/gpu_pci.c index 558a7722c..5397f0fe6 100644 --- a/src/detection/gpu/gpu_pci.c +++ b/src/detection/gpu/gpu_pci.c @@ -124,9 +124,9 @@ static void parsePciIdsFile(const FFstrbuf* content, uint8_t subclass, uint16_t } #if FF_HAVE_EMBEDDED_PCIIDS -static inline int pciDeviceCmp(const FFPciDevice* a, const FFPciDevice* b) +static inline int pciDeviceCmp(const uint16_t* key, const FFPciDevice* element) { - return (int) a->id - (int) b->id; + return (int) *key - (int) element->id; } static bool loadPciidsInc(uint8_t subclass, uint16_t vendor, uint16_t device, FFGPUResult* gpu) From 5058a934284b76eb90e467a7875a39907abbbedc Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 27 Sep 2024 10:47:57 +0800 Subject: [PATCH 54/65] GPU (Linux): use renderDN instead of cardN when detecting AMD cards Ref: https://github.com/fastfetch-cli/fastfetch/issues/1284#issuecomment-2377437210 --- src/detection/gpu/gpu_linux.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 35b50b9a8..062ab802b 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -71,9 +71,30 @@ static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer return true; } +static const char* drmFindRenderFromCard(const char* drmCardKey, FFstrbuf* result) +{ + char path[PATH_MAX]; + sprintf(path, "/sys/class/drm/%s/device/drm", drmCardKey); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(path); + if (!dirp) return "Failed to open `/sys/class/drm/{drmCardKey}/device/drm`"; + + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (ffStrStartsWith(entry->d_name, "render")) + { + ffStrbufSetS(result, "/dev/dri/"); + ffStrbufAppendS(result, entry->d_name); + return NULL; + } + } + return "Failed to find render device"; +} + static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) { #if FF_HAVE_DRM_AMDGPU + FF_LIBRARY_LOAD(libdrm, "dlopen libdrm_amdgpu" FF_LIBRARY_EXTENSION " failed", "libdrm_amdgpu" FF_LIBRARY_EXTENSION, 1) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_initialize) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_get_marketing_name) @@ -82,8 +103,10 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_query_heap_info) FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, amdgpu_device_deinitialize) - ffStrbufSetS(buffer, "/dev/dri/"); - ffStrbufAppendS(buffer, drmKey); + { + const char* error = drmFindRenderFromCard(drmKey, buffer); + if (error) return error; + } FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY); if (fd < 0) return "Failed to open DRM device"; From 842ba9fd4e16d248e47809c2b01160a42541fa6e Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 27 Sep 2024 10:58:35 +0800 Subject: [PATCH 55/65] GPU: use driver reported adapter name if available --- src/detection/gpu/gpu_amd.c | 3 +++ src/detection/gpu/gpu_bsd.c | 26 +++++++++++++------------- src/detection/gpu/gpu_intel.c | 3 +++ src/detection/gpu/gpu_linux.c | 10 ++++------ src/detection/gpu/gpu_windows.c | 9 +++++++-- 5 files changed, 30 insertions(+), 21 deletions(-) diff --git a/src/detection/gpu/gpu_amd.c b/src/detection/gpu/gpu_amd.c index 2b55c80d2..72e1d9fc0 100644 --- a/src/detection/gpu/gpu_amd.c +++ b/src/detection/gpu/gpu_amd.c @@ -68,5 +68,8 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu if (result.index) *result.type = (uint32_t) device->adlAdapterIndex; + if (result.name) + ffStrbufSetS(result.name, device->adapterString); + return NULL; } diff --git a/src/detection/gpu/gpu_bsd.c b/src/detection/gpu/gpu_bsd.c index 2f1d9cc58..99195af20 100644 --- a/src/detection/gpu/gpu_bsd.c +++ b/src/detection/gpu/gpu_bsd.c @@ -49,18 +49,6 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) gpu->deviceId = (pc->pc_sel.pc_domain * 100000ull) + (pc->pc_sel.pc_bus * 1000ull) + (pc->pc_sel.pc_dev * 10ull) + pc->pc_sel.pc_func; gpu->frequency = FF_GPU_FREQUENCY_UNSET; - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) - { - char query[32]; - snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid); - ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); - } - - if (gpu->name.length == 0) - { - ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); - } - if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA && (options->temp || options->driverSpecific)) { ffDetectNvidiaGpuInfo(&(FFGpuDriverCondition) { @@ -79,10 +67,22 @@ const char* ffDetectGPUImpl(const FFGPUOptions* options, FFlist* gpus) .type = &gpu->type, .frequency = &gpu->frequency, .coreUsage = &gpu->coreUsage, - .name = options->driverSpecific ? &gpu->name : NULL, + .name = &gpu->name, }, "libnvidia-ml.so"); } + if (gpu->name.length == 0) + { + if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_AMD) + { + char query[32]; + snprintf(query, sizeof(query), "%X,\t%X,", (unsigned) pc->pc_device, (unsigned) pc->pc_revid); + ffParsePropFileData("libdrm/amdgpu.ids", query, &gpu->name); + } + if (gpu->name.length == 0) + ffGPUFillVendorAndName(pc->pc_subclass, pc->pc_vendor, pc->pc_device, gpu); + } + if (gpu->type == FF_GPU_TYPE_UNKNOWN) { if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_NVIDIA) diff --git a/src/detection/gpu/gpu_intel.c b/src/detection/gpu/gpu_intel.c index 1b4da5ed8..ffa04ccb8 100644 --- a/src/detection/gpu/gpu_intel.c +++ b/src/detection/gpu/gpu_intel.c @@ -195,5 +195,8 @@ const char* ffDetectIntelGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverRe } } + if (result.name) + ffStrbufSetS(result.name, properties.name); + return NULL; } diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 062ab802b..276a35c97 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -302,11 +302,6 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); - if (gpu->name.length == 0) - { - ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); - } - pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); @@ -367,7 +362,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, .frequency = options->driverSpecific ? &gpu->frequency : NULL, - .name = options->driverSpecific ? &gpu->name : NULL, + .name = &gpu->name, }, soName); } @@ -388,6 +383,9 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf } } + if (gpu->name.length == 0) + ffGPUFillVendorAndName(subclassId, (uint16_t) vendorId, (uint16_t) deviceId, gpu); + return NULL; } diff --git a/src/detection/gpu/gpu_windows.c b/src/detection/gpu/gpu_windows.c index 522b2aed4..4e6939be1 100644 --- a/src/detection/gpu/gpu_windows.c +++ b/src/detection/gpu/gpu_windows.c @@ -57,8 +57,6 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* } wchar_t buffer[256]; - if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) - ffStrbufSetWS(&gpu->name, buffer); uint64_t adapterLuid = 0; @@ -175,11 +173,18 @@ const char* ffDetectGPUImpl(FF_MAYBE_UNUSED const FFGPUOptions* options, FFlist* .coreCount = options->driverSpecific ? (uint32_t*) &gpu->coreCount : NULL, .coreUsage = options->driverSpecific ? &gpu->coreUsage : NULL, .type = &gpu->type, + .name = &gpu->name, .frequency = options->driverSpecific ? &gpu->frequency : NULL, }, dllName ); } + + if (!gpu->name.length) + { + if (SetupDiGetDeviceRegistryPropertyW(hdev, &did, SPDRP_DEVICEDESC, NULL, (PBYTE) buffer, sizeof(buffer), NULL)) + ffStrbufSetWS(&gpu->name, buffer); + } } return NULL; From 7ae7ff8cef7da6a37cc9e3422c77875fe0631447 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Fri, 27 Sep 2024 16:38:01 +0800 Subject: [PATCH 56/65] GPU (Linux): detect EU count & vmem size of Intel GPUs --- src/detection/gpu/gpu_linux.c | 202 ++++- src/detection/gpu/xe_drm.h | 1377 +++++++++++++++++++++++++++++++++ 2 files changed, 1567 insertions(+), 12 deletions(-) create mode 100644 src/detection/gpu/xe_drm.h diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 276a35c97..2374e92b5 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -6,6 +6,7 @@ #include "common/library.h" #include "common/properties.h" #include "util/stringUtils.h" +#include "util/mallocHelper.h" #include @@ -15,6 +16,13 @@ #include #endif +#ifdef FF_HAVE_DRM + #include + #include "xe_drm.h" + #include + #include +#endif + #include "gpu_asahi.h" #define FF_STR_INDIR(x) #x @@ -222,7 +230,7 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu, } } -static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer) +static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey) { // Works for Intel GPUs // https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/ @@ -230,28 +238,174 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* // 0000:00:02.0 is reserved for Intel integrated graphics gpu->type = gpu->deviceId == 20 ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + if (!drmKey) return; + if (ffStrbufEqualS(&gpu->driver, "xe")) { ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq"); } else { - ffStrbufAppendS(pciDir, "/drm/"); - FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars); - if (!dirp) return; - struct dirent* entry; - while ((entry = readdir(dirp)) != NULL) - { - if (ffStrStartsWith(entry->d_name, "card")) break; - } - if (!entry) return; - ffStrbufAppendS(pciDir, entry->d_name); + ffStrbufAppendC(pciDir, '/'); + ffStrbufAppendS(pciDir, drmKey); ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); } if (ffReadFileBuffer(pciDir->chars, buffer)) gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0); } +static inline int popcountBytes(uint8_t* bytes, uint32_t length) +{ + int count = 0; + while (length >= 8) + { + count += __builtin_popcountll(*(uint64_t*) bytes); + bytes += 8; + length -= 8; + } + if (length >= 4) + { + count += __builtin_popcountl(*(uint32_t*) bytes); + bytes += 4; + length -= 4; + } + if (length >= 2) + { + count += __builtin_popcountl(*(uint16_t*) bytes); + bytes += 2; + length -= 2; + } + if (length) + { + count += __builtin_popcountl(*(uint8_t*) bytes); + } + return count; +} + +static const char* drmDetectIntelSpecific(FFGPUResult* gpu, const char* drmKey, FFstrbuf* buffer) +{ + #if FF_HAVE_DRM + ffStrbufSetS(buffer, "/dev/dri/"); + ffStrbufAppendS(buffer, drmKey); + FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY); + if (fd < 0) return "Failed to open drm device"; + + if (ffStrbufEqualS(&gpu->driver, "xe")) + { + { + struct drm_xe_device_query query = { + .extensions = 0, + .query = DRM_XE_DEVICE_QUERY_GT_TOPOLOGY, + .size = 0, + .data = 0, + }; + if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) + { + FF_AUTO_FREE uint8_t* buffer = malloc(query.size); + query.data = (uintptr_t) buffer; + if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) + { + int dssCount = 0, euPerDssCount = 0; + for (struct drm_xe_query_topology_mask* topo = (void*) buffer; + (uint8_t*) topo < buffer + query.size; + topo = (void*) (topo->mask + topo->num_bytes) + ) { + switch (topo->type) + { + case DRM_XE_TOPO_DSS_COMPUTE: + case DRM_XE_TOPO_DSS_GEOMETRY: + dssCount += popcountBytes(topo->mask, topo->num_bytes); + break; + case DRM_XE_TOPO_EU_PER_DSS: + euPerDssCount += popcountBytes(topo->mask, topo->num_bytes); + break; + } + } + gpu->coreCount = dssCount * euPerDssCount; + } + } + } + + { + struct drm_xe_device_query query = { + .query = DRM_XE_DEVICE_QUERY_MEM_REGIONS, + }; + if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) + { + FF_AUTO_FREE uint8_t* buffer = malloc(query.size); + query.data = (uintptr_t) buffer; + if (ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query) >= 0) + { + gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0; + struct drm_xe_query_mem_regions* regionInfo = (void*) buffer; + for (uint32_t i = 0; i < regionInfo->num_mem_regions; i++) + { + struct drm_xe_mem_region* region = regionInfo->mem_regions + i; + switch (region->mem_class) + { + case DRM_XE_MEM_REGION_CLASS_SYSMEM: + gpu->shared.total += region->total_size; + gpu->shared.used += region->used; + break; + case DRM_XE_MEM_REGION_CLASS_VRAM: + gpu->dedicated.total += region->total_size; + gpu->dedicated.used += region->used; + break; + } + } + } + } + } + } + else if (ffStrbufEqualS(&gpu->driver, "i915")) + { + { + int value; + drm_i915_getparam_t getparam = { .param = I915_PARAM_EU_TOTAL, .value = &value }; + if (ioctl(fd, DRM_IOCTL_I915_GETPARAM, &getparam) >= 0) + gpu->coreCount = value; + } + { + struct drm_i915_query_item queryItem = { + .query_id = DRM_I915_QUERY_MEMORY_REGIONS, + }; + struct drm_i915_query query = { + .items_ptr = (uintptr_t) &queryItem, + .num_items = 1, + }; + if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0 ) + { + FF_AUTO_FREE uint8_t* buffer = calloc(1, (size_t) queryItem.length); + queryItem.data_ptr = (uintptr_t) buffer; + if (ioctl(fd, DRM_IOCTL_I915_QUERY, &query) >= 0) + { + gpu->dedicated.total = gpu->shared.total = gpu->dedicated.used = gpu->shared.used = 0; + struct drm_i915_query_memory_regions* regionInfo = (void*) buffer; + for (uint32_t i = 0; i < regionInfo->num_regions; i++) + { + struct drm_i915_memory_region_info* region = regionInfo->regions + i; + switch (region->region.memory_class) + { + case I915_MEMORY_CLASS_SYSTEM: + gpu->shared.total += region->probed_size; + gpu->shared.used += region->probed_size - region->unallocated_size; + break; + case I915_MEMORY_CLASS_DEVICE: + gpu->dedicated.total += region->probed_size; + gpu->dedicated.used += region->probed_size - region->unallocated_size; + break; + } + } + } + } + } + } + return NULL; + #else + return "Fastfetch is not compiled with drm support"; + #endif +} + static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf* buffer, FFstrbuf* deviceDir, const char* drmKey) { const uint32_t drmDirPathLength = deviceDir->length; @@ -300,6 +454,28 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf gpu->deviceId = (pciDomain * 100000ull) + (pciBus * 1000ull) + (pciDevice * 10ull) + pciFunc; gpu->frequency = FF_GPU_FREQUENCY_UNSET; + char drmKeyBuffer[8]; + if (options->driverSpecific && !drmKey) + { + ffStrbufAppendS(deviceDir, "/drm"); + FF_AUTO_CLOSE_DIR DIR* dirp = opendir(deviceDir->chars); + if (dirp) + { + struct dirent* entry; + while ((entry = readdir(dirp)) != NULL) + { + if (ffStrStartsWith(entry->d_name, "card")) + { + strncpy(drmKeyBuffer, entry->d_name, sizeof(drmKeyBuffer) - 1); + drmKeyBuffer[sizeof(drmKeyBuffer) - 1] = '\0'; + drmKey = drmKeyBuffer; + break; + } + } + } + ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + } + if (drmKey) ffStrbufSetF(&gpu->platformApi, "DRM (%s)", drmKey); pciDetectDriver(&gpu->driver, deviceDir, buffer, drmKey); @@ -337,8 +513,10 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf } else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL) { - pciDetectIntelSpecific(gpu, deviceDir, buffer); + pciDetectIntelSpecific(gpu, deviceDir, buffer, drmKey); ffStrbufSubstrBefore(deviceDir, drmDirPathLength); + if (options->driverSpecific && drmKey) + drmDetectIntelSpecific(gpu, drmKey, buffer); } else { diff --git a/src/detection/gpu/xe_drm.h b/src/detection/gpu/xe_drm.h new file mode 100644 index 000000000..1f0b47e59 --- /dev/null +++ b/src/detection/gpu/xe_drm.h @@ -0,0 +1,1377 @@ +// https://github.com/ziglang/zig/blob/master/lib/libc/include/any-linux-any/drm/xe_drm.h + +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2023 Intel Corporation + */ + +#ifndef _XE_DRM_H_ +#define _XE_DRM_H_ + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Please note that modifications to all structs defined here are + * subject to backwards-compatibility constraints. + * Sections in this file are organized as follows: + * 1. IOCTL definition + * 2. Extension definition and helper structs + * 3. IOCTL's Query structs in the order of the Query's entries. + * 4. The rest of IOCTL structs in the order of IOCTL declaration. + */ + +/** + * DOC: Xe Device Block Diagram + * + * The diagram below represents a high-level simplification of a discrete + * GPU supported by the Xe driver. It shows some device components which + * are necessary to understand this API, as well as how their relations + * to each other. This diagram does not represent real hardware:: + * + * ┌──────────────────────────────────────────────────────────────────┐ + * │ ┌──────────────────────────────────────────────────┐ ┌─────────┐ │ + * │ │ ┌───────────────────────┐ ┌─────┐ │ │ ┌─────┐ │ │ + * │ │ │ VRAM0 ├───┤ ... │ │ │ │VRAM1│ │ │ + * │ │ └───────────┬───────────┘ └─GT1─┘ │ │ └──┬──┘ │ │ + * │ │ ┌──────────────────┴───────────────────────────┐ │ │ ┌──┴──┐ │ │ + * │ │ │ ┌─────────────────────┐ ┌─────────────────┐ │ │ │ │ │ │ │ + * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ + * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │RCS0 │ │BCS0 │ │ │ │ │ │ │ │ │ + * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ + * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ + * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │VCS0 │ │VCS1 │ │ │ │ │ │ │ │ │ + * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ + * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ + * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │VECS0│ │VECS1│ │ │ │ │ │ ... │ │ │ + * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ + * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ + * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │CCS0 │ │CCS1 │ │ │ │ │ │ │ │ │ + * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ + * │ │ │ └─────────DSS─────────┘ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ + * │ │ │ │ │CCS2 │ │CCS3 │ │ │ │ │ │ │ │ │ + * │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ + * │ │ │ │ ... │ │ ... │ │ ... │ │ │ │ │ │ │ │ │ │ + * │ │ │ └─DSS─┘ └─DSS─┘ └─DSS─┘ └─────Engines─────┘ │ │ │ │ │ │ │ + * │ │ └───────────────────────────GT0────────────────┘ │ │ └─GT2─┘ │ │ + * │ └────────────────────────────Tile0─────────────────┘ └─ Tile1──┘ │ + * └─────────────────────────────Device0───────┬──────────────────────┘ + * │ + * ───────────────────────┴────────── PCI bus + */ + +/** + * DOC: Xe uAPI Overview + * + * This section aims to describe the Xe's IOCTL entries, its structs, and other + * Xe related uAPI such as uevents and PMU (Platform Monitoring Unit) related + * entries and usage. + * + * List of supported IOCTLs: + * - &DRM_IOCTL_XE_DEVICE_QUERY + * - &DRM_IOCTL_XE_GEM_CREATE + * - &DRM_IOCTL_XE_GEM_MMAP_OFFSET + * - &DRM_IOCTL_XE_VM_CREATE + * - &DRM_IOCTL_XE_VM_DESTROY + * - &DRM_IOCTL_XE_VM_BIND + * - &DRM_IOCTL_XE_EXEC_QUEUE_CREATE + * - &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY + * - &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY + * - &DRM_IOCTL_XE_EXEC + * - &DRM_IOCTL_XE_WAIT_USER_FENCE + */ + +/* + * xe specific ioctls. + * + * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie + * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset + * against DRM_COMMAND_BASE and should be between [0x0, 0x60). + */ +#define DRM_XE_DEVICE_QUERY 0x00 +#define DRM_XE_GEM_CREATE 0x01 +#define DRM_XE_GEM_MMAP_OFFSET 0x02 +#define DRM_XE_VM_CREATE 0x03 +#define DRM_XE_VM_DESTROY 0x04 +#define DRM_XE_VM_BIND 0x05 +#define DRM_XE_EXEC_QUEUE_CREATE 0x06 +#define DRM_XE_EXEC_QUEUE_DESTROY 0x07 +#define DRM_XE_EXEC_QUEUE_GET_PROPERTY 0x08 +#define DRM_XE_EXEC 0x09 +#define DRM_XE_WAIT_USER_FENCE 0x0a +/* Must be kept compact -- no holes */ + +#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query) +#define DRM_IOCTL_XE_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_CREATE, struct drm_xe_gem_create) +#define DRM_IOCTL_XE_GEM_MMAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_MMAP_OFFSET, struct drm_xe_gem_mmap_offset) +#define DRM_IOCTL_XE_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_CREATE, struct drm_xe_vm_create) +#define DRM_IOCTL_XE_VM_DESTROY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_VM_DESTROY, struct drm_xe_vm_destroy) +#define DRM_IOCTL_XE_VM_BIND DRM_IOW(DRM_COMMAND_BASE + DRM_XE_VM_BIND, struct drm_xe_vm_bind) +#define DRM_IOCTL_XE_EXEC_QUEUE_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_CREATE, struct drm_xe_exec_queue_create) +#define DRM_IOCTL_XE_EXEC_QUEUE_DESTROY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_DESTROY, struct drm_xe_exec_queue_destroy) +#define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_GET_PROPERTY, struct drm_xe_exec_queue_get_property) +#define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec) +#define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence) + +/** + * DOC: Xe IOCTL Extensions + * + * Before detailing the IOCTLs and its structs, it is important to highlight + * that every IOCTL in Xe is extensible. + * + * Many interfaces need to grow over time. In most cases we can simply + * extend the struct and have userspace pass in more data. Another option, + * as demonstrated by Vulkan's approach to providing extensions for forward + * and backward compatibility, is to use a list of optional structs to + * provide those extra details. + * + * The key advantage to using an extension chain is that it allows us to + * redefine the interface more easily than an ever growing struct of + * increasing complexity, and for large parts of that interface to be + * entirely optional. The downside is more pointer chasing; chasing across + * the boundary with pointers encapsulated inside u64. + * + * Example chaining: + * + * .. code-block:: C + * + * struct drm_xe_user_extension ext3 { + * .next_extension = 0, // end + * .name = ..., + * }; + * struct drm_xe_user_extension ext2 { + * .next_extension = (uintptr_t)&ext3, + * .name = ..., + * }; + * struct drm_xe_user_extension ext1 { + * .next_extension = (uintptr_t)&ext2, + * .name = ..., + * }; + * + * Typically the struct drm_xe_user_extension would be embedded in some uAPI + * struct, and in this case we would feed it the head of the chain(i.e ext1), + * which would then apply all of the above extensions. +*/ + +/** + * struct drm_xe_user_extension - Base class for defining a chain of extensions + */ +struct drm_xe_user_extension { + /** + * @next_extension: + * + * Pointer to the next struct drm_xe_user_extension, or zero if the end. + */ + __u64 next_extension; + + /** + * @name: Name of the extension. + * + * Note that the name here is just some integer. + * + * Also note that the name space for this is not global for the whole + * driver, but rather its scope/meaning is limited to the specific piece + * of uAPI which has embedded the struct drm_xe_user_extension. + */ + __u32 name; + + /** + * @pad: MBZ + * + * All undefined bits must be zero. + */ + __u32 pad; +}; + +/** + * struct drm_xe_ext_set_property - Generic set property extension + * + * A generic struct that allows any of the Xe's IOCTL to be extended + * with a set_property operation. + */ +struct drm_xe_ext_set_property { + /** @base: base user extension */ + struct drm_xe_user_extension base; + + /** @property: property to set */ + __u32 property; + + /** @pad: MBZ */ + __u32 pad; + + /** @value: property value */ + __u64 value; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_engine_class_instance - instance of an engine class + * + * It is returned as part of the @drm_xe_engine, but it also is used as + * the input of engine selection for both @drm_xe_exec_queue_create and + * @drm_xe_query_engine_cycles + * + * The @engine_class can be: + * - %DRM_XE_ENGINE_CLASS_RENDER + * - %DRM_XE_ENGINE_CLASS_COPY + * - %DRM_XE_ENGINE_CLASS_VIDEO_DECODE + * - %DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE + * - %DRM_XE_ENGINE_CLASS_COMPUTE + * - %DRM_XE_ENGINE_CLASS_VM_BIND - Kernel only classes (not actual + * hardware engine class). Used for creating ordered queues of VM + * bind operations. + */ +struct drm_xe_engine_class_instance { +#define DRM_XE_ENGINE_CLASS_RENDER 0 +#define DRM_XE_ENGINE_CLASS_COPY 1 +#define DRM_XE_ENGINE_CLASS_VIDEO_DECODE 2 +#define DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE 3 +#define DRM_XE_ENGINE_CLASS_COMPUTE 4 +#define DRM_XE_ENGINE_CLASS_VM_BIND 5 + /** @engine_class: engine class id */ + __u16 engine_class; + /** @engine_instance: engine instance id */ + __u16 engine_instance; + /** @gt_id: Unique ID of this GT within the PCI Device */ + __u16 gt_id; + /** @pad: MBZ */ + __u16 pad; +}; + +/** + * struct drm_xe_engine - describe hardware engine + */ +struct drm_xe_engine { + /** @instance: The @drm_xe_engine_class_instance */ + struct drm_xe_engine_class_instance instance; + + /** @reserved: Reserved */ + __u64 reserved[3]; +}; + +/** + * struct drm_xe_query_engines - describe engines + * + * If a query is made with a struct @drm_xe_device_query where .query + * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of + * struct @drm_xe_query_engines in .data. + */ +struct drm_xe_query_engines { + /** @num_engines: number of engines returned in @engines */ + __u32 num_engines; + /** @pad: MBZ */ + __u32 pad; + /** @engines: The returned engines for this device */ + struct drm_xe_engine engines[]; +}; + +/** + * enum drm_xe_memory_class - Supported memory classes. + */ +enum drm_xe_memory_class { + /** @DRM_XE_MEM_REGION_CLASS_SYSMEM: Represents system memory. */ + DRM_XE_MEM_REGION_CLASS_SYSMEM = 0, + /** + * @DRM_XE_MEM_REGION_CLASS_VRAM: On discrete platforms, this + * represents the memory that is local to the device, which we + * call VRAM. Not valid on integrated platforms. + */ + DRM_XE_MEM_REGION_CLASS_VRAM +}; + +/** + * struct drm_xe_mem_region - Describes some region as known to + * the driver. + */ +struct drm_xe_mem_region { + /** + * @mem_class: The memory class describing this region. + * + * See enum drm_xe_memory_class for supported values. + */ + __u16 mem_class; + /** + * @instance: The unique ID for this region, which serves as the + * index in the placement bitmask used as argument for + * &DRM_IOCTL_XE_GEM_CREATE + */ + __u16 instance; + /** + * @min_page_size: Min page-size in bytes for this region. + * + * When the kernel allocates memory for this region, the + * underlying pages will be at least @min_page_size in size. + * Buffer objects with an allowable placement in this region must be + * created with a size aligned to this value. + * GPU virtual address mappings of (parts of) buffer objects that + * may be placed in this region must also have their GPU virtual + * address and range aligned to this value. + * Affected IOCTLS will return %-EINVAL if alignment restrictions are + * not met. + */ + __u32 min_page_size; + /** + * @total_size: The usable size in bytes for this region. + */ + __u64 total_size; + /** + * @used: Estimate of the memory used in bytes for this region. + * + * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable + * accounting. Without this the value here will always equal + * zero. + */ + __u64 used; + /** + * @cpu_visible_size: How much of this region can be CPU + * accessed, in bytes. + * + * This will always be <= @total_size, and the remainder (if + * any) will not be CPU accessible. If the CPU accessible part + * is smaller than @total_size then this is referred to as a + * small BAR system. + * + * On systems without small BAR (full BAR), the probed_size will + * always equal the @total_size, since all of it will be CPU + * accessible. + * + * Note this is only tracked for DRM_XE_MEM_REGION_CLASS_VRAM + * regions (for other types the value here will always equal + * zero). + */ + __u64 cpu_visible_size; + /** + * @cpu_visible_used: Estimate of CPU visible memory used, in + * bytes. + * + * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable + * accounting. Without this the value here will always equal + * zero. Note this is only currently tracked for + * DRM_XE_MEM_REGION_CLASS_VRAM regions (for other types the value + * here will always be zero). + */ + __u64 cpu_visible_used; + /** @reserved: Reserved */ + __u64 reserved[6]; +}; + +/** + * struct drm_xe_query_mem_regions - describe memory regions + * + * If a query is made with a struct drm_xe_device_query where .query + * is equal to DRM_XE_DEVICE_QUERY_MEM_REGIONS, then the reply uses + * struct drm_xe_query_mem_regions in .data. + */ +struct drm_xe_query_mem_regions { + /** @num_mem_regions: number of memory regions returned in @mem_regions */ + __u32 num_mem_regions; + /** @pad: MBZ */ + __u32 pad; + /** @mem_regions: The returned memory regions for this device */ + struct drm_xe_mem_region mem_regions[]; +}; + +/** + * struct drm_xe_query_config - describe the device configuration + * + * If a query is made with a struct drm_xe_device_query where .query + * is equal to DRM_XE_DEVICE_QUERY_CONFIG, then the reply uses + * struct drm_xe_query_config in .data. + * + * The index in @info can be: + * - %DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID - Device ID (lower 16 bits) + * and the device revision (next 8 bits) + * - %DRM_XE_QUERY_CONFIG_FLAGS - Flags describing the device + * configuration, see list below + * + * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM - Flag is set if the device + * has usable VRAM + * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment + * required by this device, typically SZ_4K or SZ_64K + * - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address + * - %DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY - Value of the highest + * available exec queue priority + */ +struct drm_xe_query_config { + /** @num_params: number of parameters returned in info */ + __u32 num_params; + + /** @pad: MBZ */ + __u32 pad; + +#define DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID 0 +#define DRM_XE_QUERY_CONFIG_FLAGS 1 + #define DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM (1 << 0) +#define DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT 2 +#define DRM_XE_QUERY_CONFIG_VA_BITS 3 +#define DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY 4 + /** @info: array of elements containing the config info */ + __u64 info[]; +}; + +/** + * struct drm_xe_gt - describe an individual GT. + * + * To be used with drm_xe_query_gt_list, which will return a list with all the + * existing GT individual descriptions. + * Graphics Technology (GT) is a subset of a GPU/tile that is responsible for + * implementing graphics and/or media operations. + * + * The index in @type can be: + * - %DRM_XE_QUERY_GT_TYPE_MAIN + * - %DRM_XE_QUERY_GT_TYPE_MEDIA + */ +struct drm_xe_gt { +#define DRM_XE_QUERY_GT_TYPE_MAIN 0 +#define DRM_XE_QUERY_GT_TYPE_MEDIA 1 + /** @type: GT type: Main or Media */ + __u16 type; + /** @tile_id: Tile ID where this GT lives (Information only) */ + __u16 tile_id; + /** @gt_id: Unique ID of this GT within the PCI Device */ + __u16 gt_id; + /** @pad: MBZ */ + __u16 pad[3]; + /** @reference_clock: A clock frequency for timestamp */ + __u32 reference_clock; + /** + * @near_mem_regions: Bit mask of instances from + * drm_xe_query_mem_regions that are nearest to the current engines + * of this GT. + * Each index in this mask refers directly to the struct + * drm_xe_query_mem_regions' instance, no assumptions should + * be made about order. The type of each region is described + * by struct drm_xe_query_mem_regions' mem_class. + */ + __u64 near_mem_regions; + /** + * @far_mem_regions: Bit mask of instances from + * drm_xe_query_mem_regions that are far from the engines of this GT. + * In general, they have extra indirections when compared to the + * @near_mem_regions. For a discrete device this could mean system + * memory and memory living in a different tile. + * Each index in this mask refers directly to the struct + * drm_xe_query_mem_regions' instance, no assumptions should + * be made about order. The type of each region is described + * by struct drm_xe_query_mem_regions' mem_class. + */ + __u64 far_mem_regions; + /** @ip_ver_major: Graphics/media IP major version on GMD_ID platforms */ + __u16 ip_ver_major; + /** @ip_ver_minor: Graphics/media IP minor version on GMD_ID platforms */ + __u16 ip_ver_minor; + /** @ip_ver_rev: Graphics/media IP revision version on GMD_ID platforms */ + __u16 ip_ver_rev; + /** @pad2: MBZ */ + __u16 pad2; + /** @reserved: Reserved */ + __u64 reserved[7]; +}; + +/** + * struct drm_xe_query_gt_list - A list with GT description items. + * + * If a query is made with a struct drm_xe_device_query where .query + * is equal to DRM_XE_DEVICE_QUERY_GT_LIST, then the reply uses struct + * drm_xe_query_gt_list in .data. + */ +struct drm_xe_query_gt_list { + /** @num_gt: number of GT items returned in gt_list */ + __u32 num_gt; + /** @pad: MBZ */ + __u32 pad; + /** @gt_list: The GT list returned for this device */ + struct drm_xe_gt gt_list[]; +}; + +/** + * struct drm_xe_query_topology_mask - describe the topology mask of a GT + * + * This is the hardware topology which reflects the internal physical + * structure of the GPU. + * + * If a query is made with a struct drm_xe_device_query where .query + * is equal to DRM_XE_DEVICE_QUERY_GT_TOPOLOGY, then the reply uses + * struct drm_xe_query_topology_mask in .data. + * + * The @type can be: + * - %DRM_XE_TOPO_DSS_GEOMETRY - To query the mask of Dual Sub Slices + * (DSS) available for geometry operations. For example a query response + * containing the following in mask: + * ``DSS_GEOMETRY ff ff ff ff 00 00 00 00`` + * means 32 DSS are available for geometry. + * - %DRM_XE_TOPO_DSS_COMPUTE - To query the mask of Dual Sub Slices + * (DSS) available for compute operations. For example a query response + * containing the following in mask: + * ``DSS_COMPUTE ff ff ff ff 00 00 00 00`` + * means 32 DSS are available for compute. + * - %DRM_XE_TOPO_EU_PER_DSS - To query the mask of Execution Units (EU) + * available per Dual Sub Slices (DSS). For example a query response + * containing the following in mask: + * ``EU_PER_DSS ff ff 00 00 00 00 00 00`` + * means each DSS has 16 EU. + */ +struct drm_xe_query_topology_mask { + /** @gt_id: GT ID the mask is associated with */ + __u16 gt_id; + +#define DRM_XE_TOPO_DSS_GEOMETRY 1 +#define DRM_XE_TOPO_DSS_COMPUTE 2 +#define DRM_XE_TOPO_EU_PER_DSS 4 + /** @type: type of mask */ + __u16 type; + + /** @num_bytes: number of bytes in requested mask */ + __u32 num_bytes; + + /** @mask: little-endian mask of @num_bytes */ + __u8 mask[]; +}; + +/** + * struct drm_xe_query_engine_cycles - correlate CPU and GPU timestamps + * + * If a query is made with a struct drm_xe_device_query where .query is equal to + * DRM_XE_DEVICE_QUERY_ENGINE_CYCLES, then the reply uses struct drm_xe_query_engine_cycles + * in .data. struct drm_xe_query_engine_cycles is allocated by the user and + * .data points to this allocated structure. + * + * The query returns the engine cycles, which along with GT's @reference_clock, + * can be used to calculate the engine timestamp. In addition the + * query returns a set of cpu timestamps that indicate when the command + * streamer cycle count was captured. + */ +struct drm_xe_query_engine_cycles { + /** + * @eci: This is input by the user and is the engine for which command + * streamer cycles is queried. + */ + struct drm_xe_engine_class_instance eci; + + /** + * @clockid: This is input by the user and is the reference clock id for + * CPU timestamp. For definition, see clock_gettime(2) and + * perf_event_open(2). Supported clock ids are CLOCK_MONOTONIC, + * CLOCK_MONOTONIC_RAW, CLOCK_REALTIME, CLOCK_BOOTTIME, CLOCK_TAI. + */ + __s32 clockid; + + /** @width: Width of the engine cycle counter in bits. */ + __u32 width; + + /** + * @engine_cycles: Engine cycles as read from its register + * at 0x358 offset. + */ + __u64 engine_cycles; + + /** + * @cpu_timestamp: CPU timestamp in ns. The timestamp is captured before + * reading the engine_cycles register using the reference clockid set by the + * user. + */ + __u64 cpu_timestamp; + + /** + * @cpu_delta: Time delta in ns captured around reading the lower dword + * of the engine_cycles register. + */ + __u64 cpu_delta; +}; + +/** + * struct drm_xe_query_uc_fw_version - query a micro-controller firmware version + * + * Given a uc_type this will return the branch, major, minor and patch version + * of the micro-controller firmware. + */ +struct drm_xe_query_uc_fw_version { + /** @uc_type: The micro-controller type to query firmware version */ +#define XE_QUERY_UC_TYPE_GUC_SUBMISSION 0 +#define XE_QUERY_UC_TYPE_HUC 1 + __u16 uc_type; + + /** @pad: MBZ */ + __u16 pad; + + /** @branch_ver: branch uc fw version */ + __u32 branch_ver; + /** @major_ver: major uc fw version */ + __u32 major_ver; + /** @minor_ver: minor uc fw version */ + __u32 minor_ver; + /** @patch_ver: patch uc fw version */ + __u32 patch_ver; + + /** @pad2: MBZ */ + __u32 pad2; + + /** @reserved: Reserved */ + __u64 reserved; +}; + +/** + * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main + * structure to query device information + * + * The user selects the type of data to query among DRM_XE_DEVICE_QUERY_* + * and sets the value in the query member. This determines the type of + * the structure provided by the driver in data, among struct drm_xe_query_*. + * + * The @query can be: + * - %DRM_XE_DEVICE_QUERY_ENGINES + * - %DRM_XE_DEVICE_QUERY_MEM_REGIONS + * - %DRM_XE_DEVICE_QUERY_CONFIG + * - %DRM_XE_DEVICE_QUERY_GT_LIST + * - %DRM_XE_DEVICE_QUERY_HWCONFIG - Query type to retrieve the hardware + * configuration of the device such as information on slices, memory, + * caches, and so on. It is provided as a table of key / value + * attributes. + * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY + * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES + * + * If size is set to 0, the driver fills it with the required size for + * the requested type of data to query. If size is equal to the required + * size, the queried information is copied into data. If size is set to + * a value different from 0 and different from the required size, the + * IOCTL call returns -EINVAL. + * + * For example the following code snippet allows retrieving and printing + * information about the device engines with DRM_XE_DEVICE_QUERY_ENGINES: + * + * .. code-block:: C + * + * struct drm_xe_query_engines *engines; + * struct drm_xe_device_query query = { + * .extensions = 0, + * .query = DRM_XE_DEVICE_QUERY_ENGINES, + * .size = 0, + * .data = 0, + * }; + * ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query); + * engines = malloc(query.size); + * query.data = (uintptr_t)engines; + * ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query); + * for (int i = 0; i < engines->num_engines; i++) { + * printf("Engine %d: %s\n", i, + * engines->engines[i].instance.engine_class == + * DRM_XE_ENGINE_CLASS_RENDER ? "RENDER": + * engines->engines[i].instance.engine_class == + * DRM_XE_ENGINE_CLASS_COPY ? "COPY": + * engines->engines[i].instance.engine_class == + * DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE": + * engines->engines[i].instance.engine_class == + * DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE": + * engines->engines[i].instance.engine_class == + * DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE": + * "UNKNOWN"); + * } + * free(engines); + */ +struct drm_xe_device_query { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + +#define DRM_XE_DEVICE_QUERY_ENGINES 0 +#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1 +#define DRM_XE_DEVICE_QUERY_CONFIG 2 +#define DRM_XE_DEVICE_QUERY_GT_LIST 3 +#define DRM_XE_DEVICE_QUERY_HWCONFIG 4 +#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5 +#define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6 +#define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7 + /** @query: The type of data to query */ + __u32 query; + + /** @size: Size of the queried data */ + __u32 size; + + /** @data: Queried data is placed here */ + __u64 data; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_gem_create - Input of &DRM_IOCTL_XE_GEM_CREATE - A structure for + * gem creation + * + * The @flags can be: + * - %DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING + * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT + * - %DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - When using VRAM as a + * possible placement, ensure that the corresponding VRAM allocation + * will always use the CPU accessible part of VRAM. This is important + * for small-bar systems (on full-bar systems this gets turned into a + * noop). + * Note1: System memory can be used as an extra placement if the kernel + * should spill the allocation to system memory, if space can't be made + * available in the CPU accessible part of VRAM (giving the same + * behaviour as the i915 interface, see + * I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS). + * Note2: For clear-color CCS surfaces the kernel needs to read the + * clear-color value stored in the buffer, and on discrete platforms we + * need to use VRAM for display surfaces, therefore the kernel requires + * setting this flag for such objects, otherwise an error is thrown on + * small-bar systems. + * + * @cpu_caching supports the following values: + * - %DRM_XE_GEM_CPU_CACHING_WB - Allocate the pages with write-back + * caching. On iGPU this can't be used for scanout surfaces. Currently + * not allowed for objects placed in VRAM. + * - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This + * is uncached. Scanout surfaces should likely use this. All objects + * that can be placed in VRAM must use this. + */ +struct drm_xe_gem_create { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** + * @size: Size of the object to be created, must match region + * (system or vram) minimum alignment (&min_page_size). + */ + __u64 size; + + /** + * @placement: A mask of memory instances of where BO can be placed. + * Each index in this mask refers directly to the struct + * drm_xe_query_mem_regions' instance, no assumptions should + * be made about order. The type of each region is described + * by struct drm_xe_query_mem_regions' mem_class. + */ + __u32 placement; + +#define DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING (1 << 0) +#define DRM_XE_GEM_CREATE_FLAG_SCANOUT (1 << 1) +#define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2) + /** + * @flags: Flags, currently a mask of memory instances of where BO can + * be placed + */ + __u32 flags; + + /** + * @vm_id: Attached VM, if any + * + * If a VM is specified, this BO must: + * + * 1. Only ever be bound to that VM. + * 2. Cannot be exported as a PRIME fd. + */ + __u32 vm_id; + + /** + * @handle: Returned handle for the object. + * + * Object handles are nonzero. + */ + __u32 handle; + +#define DRM_XE_GEM_CPU_CACHING_WB 1 +#define DRM_XE_GEM_CPU_CACHING_WC 2 + /** + * @cpu_caching: The CPU caching mode to select for this object. If + * mmaping the object the mode selected here will also be used. + */ + __u16 cpu_caching; + /** @pad: MBZ */ + __u16 pad[3]; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET + */ +struct drm_xe_gem_mmap_offset { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @handle: Handle for the object being mapped. */ + __u32 handle; + + /** @flags: Must be zero */ + __u32 flags; + + /** @offset: The fake offset to use for subsequent mmap call */ + __u64 offset; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_vm_create - Input of &DRM_IOCTL_XE_VM_CREATE + * + * The @flags can be: + * - %DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE + * - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts + * exec submissions to its exec_queues that don't have an upper time + * limit on the job execution time. But exec submissions to these + * don't allow any of the flags DRM_XE_SYNC_FLAG_SYNCOBJ, + * DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ, DRM_XE_SYNC_FLAG_DMA_BUF, + * used as out-syncobjs, that is, together with DRM_XE_SYNC_FLAG_SIGNAL. + * LR VMs can be created in recoverable page-fault mode using + * DRM_XE_VM_CREATE_FLAG_FAULT_MODE, if the device supports it. + * If that flag is omitted, the UMD can not rely on the slightly + * different per-VM overcommit semantics that are enabled by + * DRM_XE_VM_CREATE_FLAG_FAULT_MODE (see below), but KMD may + * still enable recoverable pagefaults if supported by the device. + * - %DRM_XE_VM_CREATE_FLAG_FAULT_MODE - Requires also + * DRM_XE_VM_CREATE_FLAG_LR_MODE. It allows memory to be allocated on + * demand when accessed, and also allows per-VM overcommit of memory. + * The xe driver internally uses recoverable pagefaults to implement + * this. + */ +struct drm_xe_vm_create { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + +#define DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE (1 << 0) +#define DRM_XE_VM_CREATE_FLAG_LR_MODE (1 << 1) +#define DRM_XE_VM_CREATE_FLAG_FAULT_MODE (1 << 2) + /** @flags: Flags */ + __u32 flags; + + /** @vm_id: Returned VM ID */ + __u32 vm_id; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_vm_destroy - Input of &DRM_IOCTL_XE_VM_DESTROY + */ +struct drm_xe_vm_destroy { + /** @vm_id: VM ID */ + __u32 vm_id; + + /** @pad: MBZ */ + __u32 pad; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_vm_bind_op - run bind operations + * + * The @op can be: + * - %DRM_XE_VM_BIND_OP_MAP + * - %DRM_XE_VM_BIND_OP_UNMAP + * - %DRM_XE_VM_BIND_OP_MAP_USERPTR + * - %DRM_XE_VM_BIND_OP_UNMAP_ALL + * - %DRM_XE_VM_BIND_OP_PREFETCH + * + * and the @flags can be: + * - %DRM_XE_VM_BIND_FLAG_READONLY - Setup the page tables as read-only + * to ensure write protection + * - %DRM_XE_VM_BIND_FLAG_IMMEDIATE - On a faulting VM, do the + * MAP operation immediately rather than deferring the MAP to the page + * fault handler. This is implied on a non-faulting VM as there is no + * fault handler to defer to. + * - %DRM_XE_VM_BIND_FLAG_NULL - When the NULL flag is set, the page + * tables are setup with a special bit which indicates writes are + * dropped and all reads return zero. In the future, the NULL flags + * will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO + * handle MBZ, and the BO offset MBZ. This flag is intended to + * implement VK sparse bindings. + */ +struct drm_xe_vm_bind_op { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** + * @obj: GEM object to operate on, MBZ for MAP_USERPTR, MBZ for UNMAP + */ + __u32 obj; + + /** + * @pat_index: The platform defined @pat_index to use for this mapping. + * The index basically maps to some predefined memory attributes, + * including things like caching, coherency, compression etc. The exact + * meaning of the pat_index is platform specific and defined in the + * Bspec and PRMs. When the KMD sets up the binding the index here is + * encoded into the ppGTT PTE. + * + * For coherency the @pat_index needs to be at least 1way coherent when + * drm_xe_gem_create.cpu_caching is DRM_XE_GEM_CPU_CACHING_WB. The KMD + * will extract the coherency mode from the @pat_index and reject if + * there is a mismatch (see note below for pre-MTL platforms). + * + * Note: On pre-MTL platforms there is only a caching mode and no + * explicit coherency mode, but on such hardware there is always a + * shared-LLC (or is dgpu) so all GT memory accesses are coherent with + * CPU caches even with the caching mode set as uncached. It's only the + * display engine that is incoherent (on dgpu it must be in VRAM which + * is always mapped as WC on the CPU). However to keep the uapi somewhat + * consistent with newer platforms the KMD groups the different cache + * levels into the following coherency buckets on all pre-MTL platforms: + * + * ppGTT UC -> COH_NONE + * ppGTT WC -> COH_NONE + * ppGTT WT -> COH_NONE + * ppGTT WB -> COH_AT_LEAST_1WAY + * + * In practice UC/WC/WT should only ever used for scanout surfaces on + * such platforms (or perhaps in general for dma-buf if shared with + * another device) since it is only the display engine that is actually + * incoherent. Everything else should typically use WB given that we + * have a shared-LLC. On MTL+ this completely changes and the HW + * defines the coherency mode as part of the @pat_index, where + * incoherent GT access is possible. + * + * Note: For userptr and externally imported dma-buf the kernel expects + * either 1WAY or 2WAY for the @pat_index. + * + * For DRM_XE_VM_BIND_FLAG_NULL bindings there are no KMD restrictions + * on the @pat_index. For such mappings there is no actual memory being + * mapped (the address in the PTE is invalid), so the various PAT memory + * attributes likely do not apply. Simply leaving as zero is one + * option (still a valid pat_index). + */ + __u16 pat_index; + + /** @pad: MBZ */ + __u16 pad; + + union { + /** + * @obj_offset: Offset into the object, MBZ for CLEAR_RANGE, + * ignored for unbind + */ + __u64 obj_offset; + + /** @userptr: user pointer to bind on */ + __u64 userptr; + }; + + /** + * @range: Number of bytes from the object to bind to addr, MBZ for UNMAP_ALL + */ + __u64 range; + + /** @addr: Address to operate on, MBZ for UNMAP_ALL */ + __u64 addr; + +#define DRM_XE_VM_BIND_OP_MAP 0x0 +#define DRM_XE_VM_BIND_OP_UNMAP 0x1 +#define DRM_XE_VM_BIND_OP_MAP_USERPTR 0x2 +#define DRM_XE_VM_BIND_OP_UNMAP_ALL 0x3 +#define DRM_XE_VM_BIND_OP_PREFETCH 0x4 + /** @op: Bind operation to perform */ + __u32 op; + +#define DRM_XE_VM_BIND_FLAG_READONLY (1 << 0) +#define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1) +#define DRM_XE_VM_BIND_FLAG_NULL (1 << 2) +#define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) + /** @flags: Bind flags */ + __u32 flags; + + /** + * @prefetch_mem_region_instance: Memory region to prefetch VMA to. + * It is a region instance, not a mask. + * To be used only with %DRM_XE_VM_BIND_OP_PREFETCH operation. + */ + __u32 prefetch_mem_region_instance; + + /** @pad2: MBZ */ + __u32 pad2; + + /** @reserved: Reserved */ + __u64 reserved[3]; +}; + +/** + * struct drm_xe_vm_bind - Input of &DRM_IOCTL_XE_VM_BIND + * + * Below is an example of a minimal use of @drm_xe_vm_bind to + * asynchronously bind the buffer `data` at address `BIND_ADDRESS` to + * illustrate `userptr`. It can be synchronized by using the example + * provided for @drm_xe_sync. + * + * .. code-block:: C + * + * data = aligned_alloc(ALIGNMENT, BO_SIZE); + * struct drm_xe_vm_bind bind = { + * .vm_id = vm, + * .num_binds = 1, + * .bind.obj = 0, + * .bind.obj_offset = to_user_pointer(data), + * .bind.range = BO_SIZE, + * .bind.addr = BIND_ADDRESS, + * .bind.op = DRM_XE_VM_BIND_OP_MAP_USERPTR, + * .bind.flags = 0, + * .num_syncs = 1, + * .syncs = &sync, + * .exec_queue_id = 0, + * }; + * ioctl(fd, DRM_IOCTL_XE_VM_BIND, &bind); + * + */ +struct drm_xe_vm_bind { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @vm_id: The ID of the VM to bind to */ + __u32 vm_id; + + /** + * @exec_queue_id: exec_queue_id, must be of class DRM_XE_ENGINE_CLASS_VM_BIND + * and exec queue must have same vm_id. If zero, the default VM bind engine + * is used. + */ + __u32 exec_queue_id; + + /** @pad: MBZ */ + __u32 pad; + + /** @num_binds: number of binds in this IOCTL */ + __u32 num_binds; + + union { + /** @bind: used if num_binds == 1 */ + struct drm_xe_vm_bind_op bind; + + /** + * @vector_of_binds: userptr to array of struct + * drm_xe_vm_bind_op if num_binds > 1 + */ + __u64 vector_of_binds; + }; + + /** @pad2: MBZ */ + __u32 pad2; + + /** @num_syncs: amount of syncs to wait on */ + __u32 num_syncs; + + /** @syncs: pointer to struct drm_xe_sync array */ + __u64 syncs; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE + * + * The example below shows how to use @drm_xe_exec_queue_create to create + * a simple exec_queue (no parallel submission) of class + * &DRM_XE_ENGINE_CLASS_RENDER. + * + * .. code-block:: C + * + * struct drm_xe_engine_class_instance instance = { + * .engine_class = DRM_XE_ENGINE_CLASS_RENDER, + * }; + * struct drm_xe_exec_queue_create exec_queue_create = { + * .extensions = 0, + * .vm_id = vm, + * .num_bb_per_exec = 1, + * .num_eng_per_bb = 1, + * .instances = to_user_pointer(&instance), + * }; + * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); + * + */ +struct drm_xe_exec_queue_create { +#define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 0 +#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0 +#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1 + + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @width: submission width (number BB per exec) for this exec queue */ + __u16 width; + + /** @num_placements: number of valid placements for this exec queue */ + __u16 num_placements; + + /** @vm_id: VM to use for this exec queue */ + __u32 vm_id; + + /** @flags: MBZ */ + __u32 flags; + + /** @exec_queue_id: Returned exec queue ID */ + __u32 exec_queue_id; + + /** + * @instances: user pointer to a 2-d array of struct + * drm_xe_engine_class_instance + * + * length = width (i) * num_placements (j) + * index = j + i * width + */ + __u64 instances; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_exec_queue_destroy - Input of &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY + */ +struct drm_xe_exec_queue_destroy { + /** @exec_queue_id: Exec queue ID */ + __u32 exec_queue_id; + + /** @pad: MBZ */ + __u32 pad; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_exec_queue_get_property - Input of &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY + * + * The @property can be: + * - %DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN + */ +struct drm_xe_exec_queue_get_property { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @exec_queue_id: Exec queue ID */ + __u32 exec_queue_id; + +#define DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN 0 + /** @property: property to get */ + __u32 property; + + /** @value: property value */ + __u64 value; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_sync - sync object + * + * The @type can be: + * - %DRM_XE_SYNC_TYPE_SYNCOBJ + * - %DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ + * - %DRM_XE_SYNC_TYPE_USER_FENCE + * + * and the @flags can be: + * - %DRM_XE_SYNC_FLAG_SIGNAL + * + * A minimal use of @drm_xe_sync looks like this: + * + * .. code-block:: C + * + * struct drm_xe_sync sync = { + * .flags = DRM_XE_SYNC_FLAG_SIGNAL, + * .type = DRM_XE_SYNC_TYPE_SYNCOBJ, + * }; + * struct drm_syncobj_create syncobj_create = { 0 }; + * ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create); + * sync.handle = syncobj_create.handle; + * ... + * use of &sync in drm_xe_exec or drm_xe_vm_bind + * ... + * struct drm_syncobj_wait wait = { + * .handles = &sync.handle, + * .timeout_nsec = INT64_MAX, + * .count_handles = 1, + * .flags = 0, + * .first_signaled = 0, + * .pad = 0, + * }; + * ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait); + */ +struct drm_xe_sync { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + +#define DRM_XE_SYNC_TYPE_SYNCOBJ 0x0 +#define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ 0x1 +#define DRM_XE_SYNC_TYPE_USER_FENCE 0x2 + /** @type: Type of the this sync object */ + __u32 type; + +#define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0) + /** @flags: Sync Flags */ + __u32 flags; + + union { + /** @handle: Handle for the object */ + __u32 handle; + + /** + * @addr: Address of user fence. When sync is passed in via exec + * IOCTL this is a GPU address in the VM. When sync passed in via + * VM bind IOCTL this is a user pointer. In either case, it is + * the users responsibility that this address is present and + * mapped when the user fence is signalled. Must be qword + * aligned. + */ + __u64 addr; + }; + + /** + * @timeline_value: Input for the timeline sync object. Needs to be + * different than 0 when used with %DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ. + */ + __u64 timeline_value; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_exec - Input of &DRM_IOCTL_XE_EXEC + * + * This is an example to use @drm_xe_exec for execution of the object + * at BIND_ADDRESS (see example in @drm_xe_vm_bind) by an exec_queue + * (see example in @drm_xe_exec_queue_create). It can be synchronized + * by using the example provided for @drm_xe_sync. + * + * .. code-block:: C + * + * struct drm_xe_exec exec = { + * .exec_queue_id = exec_queue, + * .syncs = &sync, + * .num_syncs = 1, + * .address = BIND_ADDRESS, + * .num_batch_buffer = 1, + * }; + * ioctl(fd, DRM_IOCTL_XE_EXEC, &exec); + * + */ +struct drm_xe_exec { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** @exec_queue_id: Exec queue ID for the batch buffer */ + __u32 exec_queue_id; + + /** @num_syncs: Amount of struct drm_xe_sync in array. */ + __u32 num_syncs; + + /** @syncs: Pointer to struct drm_xe_sync array. */ + __u64 syncs; + + /** + * @address: address of batch buffer if num_batch_buffer == 1 or an + * array of batch buffer addresses + */ + __u64 address; + + /** + * @num_batch_buffer: number of batch buffer in this exec, must match + * the width of the engine + */ + __u16 num_batch_buffer; + + /** @pad: MBZ */ + __u16 pad[3]; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +/** + * struct drm_xe_wait_user_fence - Input of &DRM_IOCTL_XE_WAIT_USER_FENCE + * + * Wait on user fence, XE will wake-up on every HW engine interrupt in the + * instances list and check if user fence is complete:: + * + * (*addr & MASK) OP (VALUE & MASK) + * + * Returns to user on user fence completion or timeout. + * + * The @op can be: + * - %DRM_XE_UFENCE_WAIT_OP_EQ + * - %DRM_XE_UFENCE_WAIT_OP_NEQ + * - %DRM_XE_UFENCE_WAIT_OP_GT + * - %DRM_XE_UFENCE_WAIT_OP_GTE + * - %DRM_XE_UFENCE_WAIT_OP_LT + * - %DRM_XE_UFENCE_WAIT_OP_LTE + * + * and the @flags can be: + * - %DRM_XE_UFENCE_WAIT_FLAG_ABSTIME + * - %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP + * + * The @mask values can be for example: + * - 0xffu for u8 + * - 0xffffu for u16 + * - 0xffffffffu for u32 + * - 0xffffffffffffffffu for u64 + */ +struct drm_xe_wait_user_fence { + /** @extensions: Pointer to the first extension struct, if any */ + __u64 extensions; + + /** + * @addr: user pointer address to wait on, must qword aligned + */ + __u64 addr; + +#define DRM_XE_UFENCE_WAIT_OP_EQ 0x0 +#define DRM_XE_UFENCE_WAIT_OP_NEQ 0x1 +#define DRM_XE_UFENCE_WAIT_OP_GT 0x2 +#define DRM_XE_UFENCE_WAIT_OP_GTE 0x3 +#define DRM_XE_UFENCE_WAIT_OP_LT 0x4 +#define DRM_XE_UFENCE_WAIT_OP_LTE 0x5 + /** @op: wait operation (type of comparison) */ + __u16 op; + +#define DRM_XE_UFENCE_WAIT_FLAG_ABSTIME (1 << 0) + /** @flags: wait flags */ + __u16 flags; + + /** @pad: MBZ */ + __u32 pad; + + /** @value: compare value */ + __u64 value; + + /** @mask: comparison mask */ + __u64 mask; + + /** + * @timeout: how long to wait before bailing, value in nanoseconds. + * Without DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag set (relative timeout) + * it contains timeout expressed in nanoseconds to wait (fence will + * expire at now() + timeout). + * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flat is set (absolute timeout) wait + * will end at timeout (uses system MONOTONIC_CLOCK). + * Passing negative timeout leads to neverending wait. + * + * On relative timeout this value is updated with timeout left + * (for restarting the call in case of signal delivery). + * On absolute timeout this value stays intact (restarted call still + * expire at the same point of time). + */ + __s64 timeout; + + /** @exec_queue_id: exec_queue_id returned from xe_exec_queue_create_ioctl */ + __u32 exec_queue_id; + + /** @pad2: MBZ */ + __u32 pad2; + + /** @reserved: Reserved */ + __u64 reserved[2]; +}; + +#if defined(__cplusplus) +} +#endif + +#endif /* _XE_DRM_H_ */ From 38f07ade447438765cb0258493d2687f6a3926cd Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 28 Sep 2024 08:13:54 +0800 Subject: [PATCH 57/65] GPU (Linux): fix building with old kernel headers --- src/detection/gpu/gpu_linux.c | 13 +- src/detection/gpu/intel_drm.h | 125 +++ src/detection/gpu/xe_drm.h | 1377 --------------------------------- 3 files changed, 128 insertions(+), 1387 deletions(-) create mode 100644 src/detection/gpu/intel_drm.h delete mode 100644 src/detection/gpu/xe_drm.h diff --git a/src/detection/gpu/gpu_linux.c b/src/detection/gpu/gpu_linux.c index 2374e92b5..2862f73c0 100644 --- a/src/detection/gpu/gpu_linux.c +++ b/src/detection/gpu/gpu_linux.c @@ -17,8 +17,7 @@ #endif #ifdef FF_HAVE_DRM - #include - #include "xe_drm.h" + #include "intel_drm.h" #include #include #endif @@ -241,15 +240,9 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* if (!drmKey) return; if (ffStrbufEqualS(&gpu->driver, "xe")) - { ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq"); - } else - { - ffStrbufAppendC(pciDir, '/'); - ffStrbufAppendS(pciDir, drmKey); - ffStrbufAppendS(pciDir, "/gt_max_freq_mhz"); - } + ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey); if (ffReadFileBuffer(pciDir->chars, buffer)) gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0); } @@ -455,7 +448,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf gpu->frequency = FF_GPU_FREQUENCY_UNSET; char drmKeyBuffer[8]; - if (options->driverSpecific && !drmKey) + if (!drmKey) { ffStrbufAppendS(deviceDir, "/drm"); FF_AUTO_CLOSE_DIR DIR* dirp = opendir(deviceDir->chars); diff --git a/src/detection/gpu/intel_drm.h b/src/detection/gpu/intel_drm.h new file mode 100644 index 000000000..97b3b07bd --- /dev/null +++ b/src/detection/gpu/intel_drm.h @@ -0,0 +1,125 @@ +#pragma once + +/* SPDX-License-Identifier: MIT */ +#include + +// xe_drm.h + +/* + * Copyright © 2023 Intel Corporation + */ + +#define DRM_XE_DEVICE_QUERY 0x00 + +#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query) + +enum drm_xe_memory_class { + DRM_XE_MEM_REGION_CLASS_SYSMEM = 0, + DRM_XE_MEM_REGION_CLASS_VRAM +}; + +struct drm_xe_mem_region { + __u16 mem_class; + __u16 instance; + __u32 min_page_size; + __u64 total_size; + __u64 used; + __u64 cpu_visible_size; + __u64 cpu_visible_used; + __u64 reserved[6]; +}; + +struct drm_xe_query_mem_regions { + __u32 num_mem_regions; + __u32 pad; + struct drm_xe_mem_region mem_regions[]; +}; + +struct drm_xe_query_topology_mask { + __u16 gt_id; + +#define DRM_XE_TOPO_DSS_GEOMETRY 1 +#define DRM_XE_TOPO_DSS_COMPUTE 2 +#define DRM_XE_TOPO_EU_PER_DSS 4 + __u16 type; + __u32 num_bytes; + __u8 mask[]; +}; + +struct drm_xe_device_query { + __u64 extensions; + +#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1 +#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5 + __u32 query; + __u32 size; + __u64 data; + __u64 reserved[2]; +}; + +// i915_drm.h + +/* + * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + */ + +#define DRM_IOCTL_I915_GETPARAM DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GETPARAM, drm_i915_getparam_t) + +struct drm_i915_getparam { + __s32 param; + int *value; +}; +typedef struct drm_i915_getparam drm_i915_getparam_t; + +#define DRM_I915_GETPARAM 0x06 +#define DRM_I915_QUERY 0x39 +#define DRM_I915_QUERY_MEMORY_REGIONS 4 +#define DRM_IOCTL_I915_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_QUERY, struct drm_i915_query) +#define I915_PARAM_EU_TOTAL 34 + +struct drm_i915_query_item { + __u64 query_id; +#define DRM_I915_QUERY_MEMORY_REGIONS 4 + + __s32 length; + __u32 flags; + __u64 data_ptr; +}; + +struct drm_i915_query { + __u32 num_items; + __u32 flags; + __u64 items_ptr; +}; + +enum drm_i915_gem_memory_class { + I915_MEMORY_CLASS_SYSTEM = 0, + I915_MEMORY_CLASS_DEVICE, +}; + +struct drm_i915_gem_memory_class_instance { + __u16 memory_class; + __u16 memory_instance; +}; + +struct drm_i915_memory_region_info { + struct drm_i915_gem_memory_class_instance region; + __u32 rsvd0; + __u64 probed_size; + __u64 unallocated_size; + + union { + __u64 rsvd1[8]; + struct { + __u64 probed_cpu_visible_size; + __u64 unallocated_cpu_visible_size; + }; + }; +}; + +struct drm_i915_query_memory_regions { + __u32 num_regions; + __u32 rsvd[3]; + struct drm_i915_memory_region_info regions[]; +}; diff --git a/src/detection/gpu/xe_drm.h b/src/detection/gpu/xe_drm.h deleted file mode 100644 index 1f0b47e59..000000000 --- a/src/detection/gpu/xe_drm.h +++ /dev/null @@ -1,1377 +0,0 @@ -// https://github.com/ziglang/zig/blob/master/lib/libc/include/any-linux-any/drm/xe_drm.h - -/* SPDX-License-Identifier: MIT */ -/* - * Copyright © 2023 Intel Corporation - */ - -#ifndef _XE_DRM_H_ -#define _XE_DRM_H_ - -#include - -#if defined(__cplusplus) -extern "C" { -#endif - -/* - * Please note that modifications to all structs defined here are - * subject to backwards-compatibility constraints. - * Sections in this file are organized as follows: - * 1. IOCTL definition - * 2. Extension definition and helper structs - * 3. IOCTL's Query structs in the order of the Query's entries. - * 4. The rest of IOCTL structs in the order of IOCTL declaration. - */ - -/** - * DOC: Xe Device Block Diagram - * - * The diagram below represents a high-level simplification of a discrete - * GPU supported by the Xe driver. It shows some device components which - * are necessary to understand this API, as well as how their relations - * to each other. This diagram does not represent real hardware:: - * - * ┌──────────────────────────────────────────────────────────────────┐ - * │ ┌──────────────────────────────────────────────────┐ ┌─────────┐ │ - * │ │ ┌───────────────────────┐ ┌─────┐ │ │ ┌─────┐ │ │ - * │ │ │ VRAM0 ├───┤ ... │ │ │ │VRAM1│ │ │ - * │ │ └───────────┬───────────┘ └─GT1─┘ │ │ └──┬──┘ │ │ - * │ │ ┌──────────────────┴───────────────────────────┐ │ │ ┌──┴──┐ │ │ - * │ │ │ ┌─────────────────────┐ ┌─────────────────┐ │ │ │ │ │ │ │ - * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ - * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │RCS0 │ │BCS0 │ │ │ │ │ │ │ │ │ - * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ - * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ - * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │VCS0 │ │VCS1 │ │ │ │ │ │ │ │ │ - * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ - * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ - * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │VECS0│ │VECS1│ │ │ │ │ │ ... │ │ │ - * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ - * │ │ │ │ ┌──┐ ┌──┐ ┌──┐ ┌──┐ │ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ - * │ │ │ │ │EU│ │EU│ │EU│ │EU│ │ │ │CCS0 │ │CCS1 │ │ │ │ │ │ │ │ │ - * │ │ │ │ └──┘ └──┘ └──┘ └──┘ │ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ - * │ │ │ └─────────DSS─────────┘ │ ┌─────┐ ┌─────┐ │ │ │ │ │ │ │ │ - * │ │ │ │ │CCS2 │ │CCS3 │ │ │ │ │ │ │ │ │ - * │ │ │ ┌─────┐ ┌─────┐ ┌─────┐ │ └─────┘ └─────┘ │ │ │ │ │ │ │ │ - * │ │ │ │ ... │ │ ... │ │ ... │ │ │ │ │ │ │ │ │ │ - * │ │ │ └─DSS─┘ └─DSS─┘ └─DSS─┘ └─────Engines─────┘ │ │ │ │ │ │ │ - * │ │ └───────────────────────────GT0────────────────┘ │ │ └─GT2─┘ │ │ - * │ └────────────────────────────Tile0─────────────────┘ └─ Tile1──┘ │ - * └─────────────────────────────Device0───────┬──────────────────────┘ - * │ - * ───────────────────────┴────────── PCI bus - */ - -/** - * DOC: Xe uAPI Overview - * - * This section aims to describe the Xe's IOCTL entries, its structs, and other - * Xe related uAPI such as uevents and PMU (Platform Monitoring Unit) related - * entries and usage. - * - * List of supported IOCTLs: - * - &DRM_IOCTL_XE_DEVICE_QUERY - * - &DRM_IOCTL_XE_GEM_CREATE - * - &DRM_IOCTL_XE_GEM_MMAP_OFFSET - * - &DRM_IOCTL_XE_VM_CREATE - * - &DRM_IOCTL_XE_VM_DESTROY - * - &DRM_IOCTL_XE_VM_BIND - * - &DRM_IOCTL_XE_EXEC_QUEUE_CREATE - * - &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY - * - &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY - * - &DRM_IOCTL_XE_EXEC - * - &DRM_IOCTL_XE_WAIT_USER_FENCE - */ - -/* - * xe specific ioctls. - * - * The device specific ioctl range is [DRM_COMMAND_BASE, DRM_COMMAND_END) ie - * [0x40, 0xa0) (a0 is excluded). The numbers below are defined as offset - * against DRM_COMMAND_BASE and should be between [0x0, 0x60). - */ -#define DRM_XE_DEVICE_QUERY 0x00 -#define DRM_XE_GEM_CREATE 0x01 -#define DRM_XE_GEM_MMAP_OFFSET 0x02 -#define DRM_XE_VM_CREATE 0x03 -#define DRM_XE_VM_DESTROY 0x04 -#define DRM_XE_VM_BIND 0x05 -#define DRM_XE_EXEC_QUEUE_CREATE 0x06 -#define DRM_XE_EXEC_QUEUE_DESTROY 0x07 -#define DRM_XE_EXEC_QUEUE_GET_PROPERTY 0x08 -#define DRM_XE_EXEC 0x09 -#define DRM_XE_WAIT_USER_FENCE 0x0a -/* Must be kept compact -- no holes */ - -#define DRM_IOCTL_XE_DEVICE_QUERY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query) -#define DRM_IOCTL_XE_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_CREATE, struct drm_xe_gem_create) -#define DRM_IOCTL_XE_GEM_MMAP_OFFSET DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_GEM_MMAP_OFFSET, struct drm_xe_gem_mmap_offset) -#define DRM_IOCTL_XE_VM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_VM_CREATE, struct drm_xe_vm_create) -#define DRM_IOCTL_XE_VM_DESTROY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_VM_DESTROY, struct drm_xe_vm_destroy) -#define DRM_IOCTL_XE_VM_BIND DRM_IOW(DRM_COMMAND_BASE + DRM_XE_VM_BIND, struct drm_xe_vm_bind) -#define DRM_IOCTL_XE_EXEC_QUEUE_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_CREATE, struct drm_xe_exec_queue_create) -#define DRM_IOCTL_XE_EXEC_QUEUE_DESTROY DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_DESTROY, struct drm_xe_exec_queue_destroy) -#define DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EXEC_QUEUE_GET_PROPERTY, struct drm_xe_exec_queue_get_property) -#define DRM_IOCTL_XE_EXEC DRM_IOW(DRM_COMMAND_BASE + DRM_XE_EXEC, struct drm_xe_exec) -#define DRM_IOCTL_XE_WAIT_USER_FENCE DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence) - -/** - * DOC: Xe IOCTL Extensions - * - * Before detailing the IOCTLs and its structs, it is important to highlight - * that every IOCTL in Xe is extensible. - * - * Many interfaces need to grow over time. In most cases we can simply - * extend the struct and have userspace pass in more data. Another option, - * as demonstrated by Vulkan's approach to providing extensions for forward - * and backward compatibility, is to use a list of optional structs to - * provide those extra details. - * - * The key advantage to using an extension chain is that it allows us to - * redefine the interface more easily than an ever growing struct of - * increasing complexity, and for large parts of that interface to be - * entirely optional. The downside is more pointer chasing; chasing across - * the boundary with pointers encapsulated inside u64. - * - * Example chaining: - * - * .. code-block:: C - * - * struct drm_xe_user_extension ext3 { - * .next_extension = 0, // end - * .name = ..., - * }; - * struct drm_xe_user_extension ext2 { - * .next_extension = (uintptr_t)&ext3, - * .name = ..., - * }; - * struct drm_xe_user_extension ext1 { - * .next_extension = (uintptr_t)&ext2, - * .name = ..., - * }; - * - * Typically the struct drm_xe_user_extension would be embedded in some uAPI - * struct, and in this case we would feed it the head of the chain(i.e ext1), - * which would then apply all of the above extensions. -*/ - -/** - * struct drm_xe_user_extension - Base class for defining a chain of extensions - */ -struct drm_xe_user_extension { - /** - * @next_extension: - * - * Pointer to the next struct drm_xe_user_extension, or zero if the end. - */ - __u64 next_extension; - - /** - * @name: Name of the extension. - * - * Note that the name here is just some integer. - * - * Also note that the name space for this is not global for the whole - * driver, but rather its scope/meaning is limited to the specific piece - * of uAPI which has embedded the struct drm_xe_user_extension. - */ - __u32 name; - - /** - * @pad: MBZ - * - * All undefined bits must be zero. - */ - __u32 pad; -}; - -/** - * struct drm_xe_ext_set_property - Generic set property extension - * - * A generic struct that allows any of the Xe's IOCTL to be extended - * with a set_property operation. - */ -struct drm_xe_ext_set_property { - /** @base: base user extension */ - struct drm_xe_user_extension base; - - /** @property: property to set */ - __u32 property; - - /** @pad: MBZ */ - __u32 pad; - - /** @value: property value */ - __u64 value; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_engine_class_instance - instance of an engine class - * - * It is returned as part of the @drm_xe_engine, but it also is used as - * the input of engine selection for both @drm_xe_exec_queue_create and - * @drm_xe_query_engine_cycles - * - * The @engine_class can be: - * - %DRM_XE_ENGINE_CLASS_RENDER - * - %DRM_XE_ENGINE_CLASS_COPY - * - %DRM_XE_ENGINE_CLASS_VIDEO_DECODE - * - %DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE - * - %DRM_XE_ENGINE_CLASS_COMPUTE - * - %DRM_XE_ENGINE_CLASS_VM_BIND - Kernel only classes (not actual - * hardware engine class). Used for creating ordered queues of VM - * bind operations. - */ -struct drm_xe_engine_class_instance { -#define DRM_XE_ENGINE_CLASS_RENDER 0 -#define DRM_XE_ENGINE_CLASS_COPY 1 -#define DRM_XE_ENGINE_CLASS_VIDEO_DECODE 2 -#define DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE 3 -#define DRM_XE_ENGINE_CLASS_COMPUTE 4 -#define DRM_XE_ENGINE_CLASS_VM_BIND 5 - /** @engine_class: engine class id */ - __u16 engine_class; - /** @engine_instance: engine instance id */ - __u16 engine_instance; - /** @gt_id: Unique ID of this GT within the PCI Device */ - __u16 gt_id; - /** @pad: MBZ */ - __u16 pad; -}; - -/** - * struct drm_xe_engine - describe hardware engine - */ -struct drm_xe_engine { - /** @instance: The @drm_xe_engine_class_instance */ - struct drm_xe_engine_class_instance instance; - - /** @reserved: Reserved */ - __u64 reserved[3]; -}; - -/** - * struct drm_xe_query_engines - describe engines - * - * If a query is made with a struct @drm_xe_device_query where .query - * is equal to %DRM_XE_DEVICE_QUERY_ENGINES, then the reply uses an array of - * struct @drm_xe_query_engines in .data. - */ -struct drm_xe_query_engines { - /** @num_engines: number of engines returned in @engines */ - __u32 num_engines; - /** @pad: MBZ */ - __u32 pad; - /** @engines: The returned engines for this device */ - struct drm_xe_engine engines[]; -}; - -/** - * enum drm_xe_memory_class - Supported memory classes. - */ -enum drm_xe_memory_class { - /** @DRM_XE_MEM_REGION_CLASS_SYSMEM: Represents system memory. */ - DRM_XE_MEM_REGION_CLASS_SYSMEM = 0, - /** - * @DRM_XE_MEM_REGION_CLASS_VRAM: On discrete platforms, this - * represents the memory that is local to the device, which we - * call VRAM. Not valid on integrated platforms. - */ - DRM_XE_MEM_REGION_CLASS_VRAM -}; - -/** - * struct drm_xe_mem_region - Describes some region as known to - * the driver. - */ -struct drm_xe_mem_region { - /** - * @mem_class: The memory class describing this region. - * - * See enum drm_xe_memory_class for supported values. - */ - __u16 mem_class; - /** - * @instance: The unique ID for this region, which serves as the - * index in the placement bitmask used as argument for - * &DRM_IOCTL_XE_GEM_CREATE - */ - __u16 instance; - /** - * @min_page_size: Min page-size in bytes for this region. - * - * When the kernel allocates memory for this region, the - * underlying pages will be at least @min_page_size in size. - * Buffer objects with an allowable placement in this region must be - * created with a size aligned to this value. - * GPU virtual address mappings of (parts of) buffer objects that - * may be placed in this region must also have their GPU virtual - * address and range aligned to this value. - * Affected IOCTLS will return %-EINVAL if alignment restrictions are - * not met. - */ - __u32 min_page_size; - /** - * @total_size: The usable size in bytes for this region. - */ - __u64 total_size; - /** - * @used: Estimate of the memory used in bytes for this region. - * - * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable - * accounting. Without this the value here will always equal - * zero. - */ - __u64 used; - /** - * @cpu_visible_size: How much of this region can be CPU - * accessed, in bytes. - * - * This will always be <= @total_size, and the remainder (if - * any) will not be CPU accessible. If the CPU accessible part - * is smaller than @total_size then this is referred to as a - * small BAR system. - * - * On systems without small BAR (full BAR), the probed_size will - * always equal the @total_size, since all of it will be CPU - * accessible. - * - * Note this is only tracked for DRM_XE_MEM_REGION_CLASS_VRAM - * regions (for other types the value here will always equal - * zero). - */ - __u64 cpu_visible_size; - /** - * @cpu_visible_used: Estimate of CPU visible memory used, in - * bytes. - * - * Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable - * accounting. Without this the value here will always equal - * zero. Note this is only currently tracked for - * DRM_XE_MEM_REGION_CLASS_VRAM regions (for other types the value - * here will always be zero). - */ - __u64 cpu_visible_used; - /** @reserved: Reserved */ - __u64 reserved[6]; -}; - -/** - * struct drm_xe_query_mem_regions - describe memory regions - * - * If a query is made with a struct drm_xe_device_query where .query - * is equal to DRM_XE_DEVICE_QUERY_MEM_REGIONS, then the reply uses - * struct drm_xe_query_mem_regions in .data. - */ -struct drm_xe_query_mem_regions { - /** @num_mem_regions: number of memory regions returned in @mem_regions */ - __u32 num_mem_regions; - /** @pad: MBZ */ - __u32 pad; - /** @mem_regions: The returned memory regions for this device */ - struct drm_xe_mem_region mem_regions[]; -}; - -/** - * struct drm_xe_query_config - describe the device configuration - * - * If a query is made with a struct drm_xe_device_query where .query - * is equal to DRM_XE_DEVICE_QUERY_CONFIG, then the reply uses - * struct drm_xe_query_config in .data. - * - * The index in @info can be: - * - %DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID - Device ID (lower 16 bits) - * and the device revision (next 8 bits) - * - %DRM_XE_QUERY_CONFIG_FLAGS - Flags describing the device - * configuration, see list below - * - * - %DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM - Flag is set if the device - * has usable VRAM - * - %DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT - Minimal memory alignment - * required by this device, typically SZ_4K or SZ_64K - * - %DRM_XE_QUERY_CONFIG_VA_BITS - Maximum bits of a virtual address - * - %DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY - Value of the highest - * available exec queue priority - */ -struct drm_xe_query_config { - /** @num_params: number of parameters returned in info */ - __u32 num_params; - - /** @pad: MBZ */ - __u32 pad; - -#define DRM_XE_QUERY_CONFIG_REV_AND_DEVICE_ID 0 -#define DRM_XE_QUERY_CONFIG_FLAGS 1 - #define DRM_XE_QUERY_CONFIG_FLAG_HAS_VRAM (1 << 0) -#define DRM_XE_QUERY_CONFIG_MIN_ALIGNMENT 2 -#define DRM_XE_QUERY_CONFIG_VA_BITS 3 -#define DRM_XE_QUERY_CONFIG_MAX_EXEC_QUEUE_PRIORITY 4 - /** @info: array of elements containing the config info */ - __u64 info[]; -}; - -/** - * struct drm_xe_gt - describe an individual GT. - * - * To be used with drm_xe_query_gt_list, which will return a list with all the - * existing GT individual descriptions. - * Graphics Technology (GT) is a subset of a GPU/tile that is responsible for - * implementing graphics and/or media operations. - * - * The index in @type can be: - * - %DRM_XE_QUERY_GT_TYPE_MAIN - * - %DRM_XE_QUERY_GT_TYPE_MEDIA - */ -struct drm_xe_gt { -#define DRM_XE_QUERY_GT_TYPE_MAIN 0 -#define DRM_XE_QUERY_GT_TYPE_MEDIA 1 - /** @type: GT type: Main or Media */ - __u16 type; - /** @tile_id: Tile ID where this GT lives (Information only) */ - __u16 tile_id; - /** @gt_id: Unique ID of this GT within the PCI Device */ - __u16 gt_id; - /** @pad: MBZ */ - __u16 pad[3]; - /** @reference_clock: A clock frequency for timestamp */ - __u32 reference_clock; - /** - * @near_mem_regions: Bit mask of instances from - * drm_xe_query_mem_regions that are nearest to the current engines - * of this GT. - * Each index in this mask refers directly to the struct - * drm_xe_query_mem_regions' instance, no assumptions should - * be made about order. The type of each region is described - * by struct drm_xe_query_mem_regions' mem_class. - */ - __u64 near_mem_regions; - /** - * @far_mem_regions: Bit mask of instances from - * drm_xe_query_mem_regions that are far from the engines of this GT. - * In general, they have extra indirections when compared to the - * @near_mem_regions. For a discrete device this could mean system - * memory and memory living in a different tile. - * Each index in this mask refers directly to the struct - * drm_xe_query_mem_regions' instance, no assumptions should - * be made about order. The type of each region is described - * by struct drm_xe_query_mem_regions' mem_class. - */ - __u64 far_mem_regions; - /** @ip_ver_major: Graphics/media IP major version on GMD_ID platforms */ - __u16 ip_ver_major; - /** @ip_ver_minor: Graphics/media IP minor version on GMD_ID platforms */ - __u16 ip_ver_minor; - /** @ip_ver_rev: Graphics/media IP revision version on GMD_ID platforms */ - __u16 ip_ver_rev; - /** @pad2: MBZ */ - __u16 pad2; - /** @reserved: Reserved */ - __u64 reserved[7]; -}; - -/** - * struct drm_xe_query_gt_list - A list with GT description items. - * - * If a query is made with a struct drm_xe_device_query where .query - * is equal to DRM_XE_DEVICE_QUERY_GT_LIST, then the reply uses struct - * drm_xe_query_gt_list in .data. - */ -struct drm_xe_query_gt_list { - /** @num_gt: number of GT items returned in gt_list */ - __u32 num_gt; - /** @pad: MBZ */ - __u32 pad; - /** @gt_list: The GT list returned for this device */ - struct drm_xe_gt gt_list[]; -}; - -/** - * struct drm_xe_query_topology_mask - describe the topology mask of a GT - * - * This is the hardware topology which reflects the internal physical - * structure of the GPU. - * - * If a query is made with a struct drm_xe_device_query where .query - * is equal to DRM_XE_DEVICE_QUERY_GT_TOPOLOGY, then the reply uses - * struct drm_xe_query_topology_mask in .data. - * - * The @type can be: - * - %DRM_XE_TOPO_DSS_GEOMETRY - To query the mask of Dual Sub Slices - * (DSS) available for geometry operations. For example a query response - * containing the following in mask: - * ``DSS_GEOMETRY ff ff ff ff 00 00 00 00`` - * means 32 DSS are available for geometry. - * - %DRM_XE_TOPO_DSS_COMPUTE - To query the mask of Dual Sub Slices - * (DSS) available for compute operations. For example a query response - * containing the following in mask: - * ``DSS_COMPUTE ff ff ff ff 00 00 00 00`` - * means 32 DSS are available for compute. - * - %DRM_XE_TOPO_EU_PER_DSS - To query the mask of Execution Units (EU) - * available per Dual Sub Slices (DSS). For example a query response - * containing the following in mask: - * ``EU_PER_DSS ff ff 00 00 00 00 00 00`` - * means each DSS has 16 EU. - */ -struct drm_xe_query_topology_mask { - /** @gt_id: GT ID the mask is associated with */ - __u16 gt_id; - -#define DRM_XE_TOPO_DSS_GEOMETRY 1 -#define DRM_XE_TOPO_DSS_COMPUTE 2 -#define DRM_XE_TOPO_EU_PER_DSS 4 - /** @type: type of mask */ - __u16 type; - - /** @num_bytes: number of bytes in requested mask */ - __u32 num_bytes; - - /** @mask: little-endian mask of @num_bytes */ - __u8 mask[]; -}; - -/** - * struct drm_xe_query_engine_cycles - correlate CPU and GPU timestamps - * - * If a query is made with a struct drm_xe_device_query where .query is equal to - * DRM_XE_DEVICE_QUERY_ENGINE_CYCLES, then the reply uses struct drm_xe_query_engine_cycles - * in .data. struct drm_xe_query_engine_cycles is allocated by the user and - * .data points to this allocated structure. - * - * The query returns the engine cycles, which along with GT's @reference_clock, - * can be used to calculate the engine timestamp. In addition the - * query returns a set of cpu timestamps that indicate when the command - * streamer cycle count was captured. - */ -struct drm_xe_query_engine_cycles { - /** - * @eci: This is input by the user and is the engine for which command - * streamer cycles is queried. - */ - struct drm_xe_engine_class_instance eci; - - /** - * @clockid: This is input by the user and is the reference clock id for - * CPU timestamp. For definition, see clock_gettime(2) and - * perf_event_open(2). Supported clock ids are CLOCK_MONOTONIC, - * CLOCK_MONOTONIC_RAW, CLOCK_REALTIME, CLOCK_BOOTTIME, CLOCK_TAI. - */ - __s32 clockid; - - /** @width: Width of the engine cycle counter in bits. */ - __u32 width; - - /** - * @engine_cycles: Engine cycles as read from its register - * at 0x358 offset. - */ - __u64 engine_cycles; - - /** - * @cpu_timestamp: CPU timestamp in ns. The timestamp is captured before - * reading the engine_cycles register using the reference clockid set by the - * user. - */ - __u64 cpu_timestamp; - - /** - * @cpu_delta: Time delta in ns captured around reading the lower dword - * of the engine_cycles register. - */ - __u64 cpu_delta; -}; - -/** - * struct drm_xe_query_uc_fw_version - query a micro-controller firmware version - * - * Given a uc_type this will return the branch, major, minor and patch version - * of the micro-controller firmware. - */ -struct drm_xe_query_uc_fw_version { - /** @uc_type: The micro-controller type to query firmware version */ -#define XE_QUERY_UC_TYPE_GUC_SUBMISSION 0 -#define XE_QUERY_UC_TYPE_HUC 1 - __u16 uc_type; - - /** @pad: MBZ */ - __u16 pad; - - /** @branch_ver: branch uc fw version */ - __u32 branch_ver; - /** @major_ver: major uc fw version */ - __u32 major_ver; - /** @minor_ver: minor uc fw version */ - __u32 minor_ver; - /** @patch_ver: patch uc fw version */ - __u32 patch_ver; - - /** @pad2: MBZ */ - __u32 pad2; - - /** @reserved: Reserved */ - __u64 reserved; -}; - -/** - * struct drm_xe_device_query - Input of &DRM_IOCTL_XE_DEVICE_QUERY - main - * structure to query device information - * - * The user selects the type of data to query among DRM_XE_DEVICE_QUERY_* - * and sets the value in the query member. This determines the type of - * the structure provided by the driver in data, among struct drm_xe_query_*. - * - * The @query can be: - * - %DRM_XE_DEVICE_QUERY_ENGINES - * - %DRM_XE_DEVICE_QUERY_MEM_REGIONS - * - %DRM_XE_DEVICE_QUERY_CONFIG - * - %DRM_XE_DEVICE_QUERY_GT_LIST - * - %DRM_XE_DEVICE_QUERY_HWCONFIG - Query type to retrieve the hardware - * configuration of the device such as information on slices, memory, - * caches, and so on. It is provided as a table of key / value - * attributes. - * - %DRM_XE_DEVICE_QUERY_GT_TOPOLOGY - * - %DRM_XE_DEVICE_QUERY_ENGINE_CYCLES - * - * If size is set to 0, the driver fills it with the required size for - * the requested type of data to query. If size is equal to the required - * size, the queried information is copied into data. If size is set to - * a value different from 0 and different from the required size, the - * IOCTL call returns -EINVAL. - * - * For example the following code snippet allows retrieving and printing - * information about the device engines with DRM_XE_DEVICE_QUERY_ENGINES: - * - * .. code-block:: C - * - * struct drm_xe_query_engines *engines; - * struct drm_xe_device_query query = { - * .extensions = 0, - * .query = DRM_XE_DEVICE_QUERY_ENGINES, - * .size = 0, - * .data = 0, - * }; - * ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query); - * engines = malloc(query.size); - * query.data = (uintptr_t)engines; - * ioctl(fd, DRM_IOCTL_XE_DEVICE_QUERY, &query); - * for (int i = 0; i < engines->num_engines; i++) { - * printf("Engine %d: %s\n", i, - * engines->engines[i].instance.engine_class == - * DRM_XE_ENGINE_CLASS_RENDER ? "RENDER": - * engines->engines[i].instance.engine_class == - * DRM_XE_ENGINE_CLASS_COPY ? "COPY": - * engines->engines[i].instance.engine_class == - * DRM_XE_ENGINE_CLASS_VIDEO_DECODE ? "VIDEO_DECODE": - * engines->engines[i].instance.engine_class == - * DRM_XE_ENGINE_CLASS_VIDEO_ENHANCE ? "VIDEO_ENHANCE": - * engines->engines[i].instance.engine_class == - * DRM_XE_ENGINE_CLASS_COMPUTE ? "COMPUTE": - * "UNKNOWN"); - * } - * free(engines); - */ -struct drm_xe_device_query { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - -#define DRM_XE_DEVICE_QUERY_ENGINES 0 -#define DRM_XE_DEVICE_QUERY_MEM_REGIONS 1 -#define DRM_XE_DEVICE_QUERY_CONFIG 2 -#define DRM_XE_DEVICE_QUERY_GT_LIST 3 -#define DRM_XE_DEVICE_QUERY_HWCONFIG 4 -#define DRM_XE_DEVICE_QUERY_GT_TOPOLOGY 5 -#define DRM_XE_DEVICE_QUERY_ENGINE_CYCLES 6 -#define DRM_XE_DEVICE_QUERY_UC_FW_VERSION 7 - /** @query: The type of data to query */ - __u32 query; - - /** @size: Size of the queried data */ - __u32 size; - - /** @data: Queried data is placed here */ - __u64 data; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_gem_create - Input of &DRM_IOCTL_XE_GEM_CREATE - A structure for - * gem creation - * - * The @flags can be: - * - %DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING - * - %DRM_XE_GEM_CREATE_FLAG_SCANOUT - * - %DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM - When using VRAM as a - * possible placement, ensure that the corresponding VRAM allocation - * will always use the CPU accessible part of VRAM. This is important - * for small-bar systems (on full-bar systems this gets turned into a - * noop). - * Note1: System memory can be used as an extra placement if the kernel - * should spill the allocation to system memory, if space can't be made - * available in the CPU accessible part of VRAM (giving the same - * behaviour as the i915 interface, see - * I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS). - * Note2: For clear-color CCS surfaces the kernel needs to read the - * clear-color value stored in the buffer, and on discrete platforms we - * need to use VRAM for display surfaces, therefore the kernel requires - * setting this flag for such objects, otherwise an error is thrown on - * small-bar systems. - * - * @cpu_caching supports the following values: - * - %DRM_XE_GEM_CPU_CACHING_WB - Allocate the pages with write-back - * caching. On iGPU this can't be used for scanout surfaces. Currently - * not allowed for objects placed in VRAM. - * - %DRM_XE_GEM_CPU_CACHING_WC - Allocate the pages as write-combined. This - * is uncached. Scanout surfaces should likely use this. All objects - * that can be placed in VRAM must use this. - */ -struct drm_xe_gem_create { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** - * @size: Size of the object to be created, must match region - * (system or vram) minimum alignment (&min_page_size). - */ - __u64 size; - - /** - * @placement: A mask of memory instances of where BO can be placed. - * Each index in this mask refers directly to the struct - * drm_xe_query_mem_regions' instance, no assumptions should - * be made about order. The type of each region is described - * by struct drm_xe_query_mem_regions' mem_class. - */ - __u32 placement; - -#define DRM_XE_GEM_CREATE_FLAG_DEFER_BACKING (1 << 0) -#define DRM_XE_GEM_CREATE_FLAG_SCANOUT (1 << 1) -#define DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM (1 << 2) - /** - * @flags: Flags, currently a mask of memory instances of where BO can - * be placed - */ - __u32 flags; - - /** - * @vm_id: Attached VM, if any - * - * If a VM is specified, this BO must: - * - * 1. Only ever be bound to that VM. - * 2. Cannot be exported as a PRIME fd. - */ - __u32 vm_id; - - /** - * @handle: Returned handle for the object. - * - * Object handles are nonzero. - */ - __u32 handle; - -#define DRM_XE_GEM_CPU_CACHING_WB 1 -#define DRM_XE_GEM_CPU_CACHING_WC 2 - /** - * @cpu_caching: The CPU caching mode to select for this object. If - * mmaping the object the mode selected here will also be used. - */ - __u16 cpu_caching; - /** @pad: MBZ */ - __u16 pad[3]; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_gem_mmap_offset - Input of &DRM_IOCTL_XE_GEM_MMAP_OFFSET - */ -struct drm_xe_gem_mmap_offset { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @handle: Handle for the object being mapped. */ - __u32 handle; - - /** @flags: Must be zero */ - __u32 flags; - - /** @offset: The fake offset to use for subsequent mmap call */ - __u64 offset; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_vm_create - Input of &DRM_IOCTL_XE_VM_CREATE - * - * The @flags can be: - * - %DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE - * - %DRM_XE_VM_CREATE_FLAG_LR_MODE - An LR, or Long Running VM accepts - * exec submissions to its exec_queues that don't have an upper time - * limit on the job execution time. But exec submissions to these - * don't allow any of the flags DRM_XE_SYNC_FLAG_SYNCOBJ, - * DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ, DRM_XE_SYNC_FLAG_DMA_BUF, - * used as out-syncobjs, that is, together with DRM_XE_SYNC_FLAG_SIGNAL. - * LR VMs can be created in recoverable page-fault mode using - * DRM_XE_VM_CREATE_FLAG_FAULT_MODE, if the device supports it. - * If that flag is omitted, the UMD can not rely on the slightly - * different per-VM overcommit semantics that are enabled by - * DRM_XE_VM_CREATE_FLAG_FAULT_MODE (see below), but KMD may - * still enable recoverable pagefaults if supported by the device. - * - %DRM_XE_VM_CREATE_FLAG_FAULT_MODE - Requires also - * DRM_XE_VM_CREATE_FLAG_LR_MODE. It allows memory to be allocated on - * demand when accessed, and also allows per-VM overcommit of memory. - * The xe driver internally uses recoverable pagefaults to implement - * this. - */ -struct drm_xe_vm_create { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - -#define DRM_XE_VM_CREATE_FLAG_SCRATCH_PAGE (1 << 0) -#define DRM_XE_VM_CREATE_FLAG_LR_MODE (1 << 1) -#define DRM_XE_VM_CREATE_FLAG_FAULT_MODE (1 << 2) - /** @flags: Flags */ - __u32 flags; - - /** @vm_id: Returned VM ID */ - __u32 vm_id; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_vm_destroy - Input of &DRM_IOCTL_XE_VM_DESTROY - */ -struct drm_xe_vm_destroy { - /** @vm_id: VM ID */ - __u32 vm_id; - - /** @pad: MBZ */ - __u32 pad; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_vm_bind_op - run bind operations - * - * The @op can be: - * - %DRM_XE_VM_BIND_OP_MAP - * - %DRM_XE_VM_BIND_OP_UNMAP - * - %DRM_XE_VM_BIND_OP_MAP_USERPTR - * - %DRM_XE_VM_BIND_OP_UNMAP_ALL - * - %DRM_XE_VM_BIND_OP_PREFETCH - * - * and the @flags can be: - * - %DRM_XE_VM_BIND_FLAG_READONLY - Setup the page tables as read-only - * to ensure write protection - * - %DRM_XE_VM_BIND_FLAG_IMMEDIATE - On a faulting VM, do the - * MAP operation immediately rather than deferring the MAP to the page - * fault handler. This is implied on a non-faulting VM as there is no - * fault handler to defer to. - * - %DRM_XE_VM_BIND_FLAG_NULL - When the NULL flag is set, the page - * tables are setup with a special bit which indicates writes are - * dropped and all reads return zero. In the future, the NULL flags - * will only be valid for DRM_XE_VM_BIND_OP_MAP operations, the BO - * handle MBZ, and the BO offset MBZ. This flag is intended to - * implement VK sparse bindings. - */ -struct drm_xe_vm_bind_op { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** - * @obj: GEM object to operate on, MBZ for MAP_USERPTR, MBZ for UNMAP - */ - __u32 obj; - - /** - * @pat_index: The platform defined @pat_index to use for this mapping. - * The index basically maps to some predefined memory attributes, - * including things like caching, coherency, compression etc. The exact - * meaning of the pat_index is platform specific and defined in the - * Bspec and PRMs. When the KMD sets up the binding the index here is - * encoded into the ppGTT PTE. - * - * For coherency the @pat_index needs to be at least 1way coherent when - * drm_xe_gem_create.cpu_caching is DRM_XE_GEM_CPU_CACHING_WB. The KMD - * will extract the coherency mode from the @pat_index and reject if - * there is a mismatch (see note below for pre-MTL platforms). - * - * Note: On pre-MTL platforms there is only a caching mode and no - * explicit coherency mode, but on such hardware there is always a - * shared-LLC (or is dgpu) so all GT memory accesses are coherent with - * CPU caches even with the caching mode set as uncached. It's only the - * display engine that is incoherent (on dgpu it must be in VRAM which - * is always mapped as WC on the CPU). However to keep the uapi somewhat - * consistent with newer platforms the KMD groups the different cache - * levels into the following coherency buckets on all pre-MTL platforms: - * - * ppGTT UC -> COH_NONE - * ppGTT WC -> COH_NONE - * ppGTT WT -> COH_NONE - * ppGTT WB -> COH_AT_LEAST_1WAY - * - * In practice UC/WC/WT should only ever used for scanout surfaces on - * such platforms (or perhaps in general for dma-buf if shared with - * another device) since it is only the display engine that is actually - * incoherent. Everything else should typically use WB given that we - * have a shared-LLC. On MTL+ this completely changes and the HW - * defines the coherency mode as part of the @pat_index, where - * incoherent GT access is possible. - * - * Note: For userptr and externally imported dma-buf the kernel expects - * either 1WAY or 2WAY for the @pat_index. - * - * For DRM_XE_VM_BIND_FLAG_NULL bindings there are no KMD restrictions - * on the @pat_index. For such mappings there is no actual memory being - * mapped (the address in the PTE is invalid), so the various PAT memory - * attributes likely do not apply. Simply leaving as zero is one - * option (still a valid pat_index). - */ - __u16 pat_index; - - /** @pad: MBZ */ - __u16 pad; - - union { - /** - * @obj_offset: Offset into the object, MBZ for CLEAR_RANGE, - * ignored for unbind - */ - __u64 obj_offset; - - /** @userptr: user pointer to bind on */ - __u64 userptr; - }; - - /** - * @range: Number of bytes from the object to bind to addr, MBZ for UNMAP_ALL - */ - __u64 range; - - /** @addr: Address to operate on, MBZ for UNMAP_ALL */ - __u64 addr; - -#define DRM_XE_VM_BIND_OP_MAP 0x0 -#define DRM_XE_VM_BIND_OP_UNMAP 0x1 -#define DRM_XE_VM_BIND_OP_MAP_USERPTR 0x2 -#define DRM_XE_VM_BIND_OP_UNMAP_ALL 0x3 -#define DRM_XE_VM_BIND_OP_PREFETCH 0x4 - /** @op: Bind operation to perform */ - __u32 op; - -#define DRM_XE_VM_BIND_FLAG_READONLY (1 << 0) -#define DRM_XE_VM_BIND_FLAG_IMMEDIATE (1 << 1) -#define DRM_XE_VM_BIND_FLAG_NULL (1 << 2) -#define DRM_XE_VM_BIND_FLAG_DUMPABLE (1 << 3) - /** @flags: Bind flags */ - __u32 flags; - - /** - * @prefetch_mem_region_instance: Memory region to prefetch VMA to. - * It is a region instance, not a mask. - * To be used only with %DRM_XE_VM_BIND_OP_PREFETCH operation. - */ - __u32 prefetch_mem_region_instance; - - /** @pad2: MBZ */ - __u32 pad2; - - /** @reserved: Reserved */ - __u64 reserved[3]; -}; - -/** - * struct drm_xe_vm_bind - Input of &DRM_IOCTL_XE_VM_BIND - * - * Below is an example of a minimal use of @drm_xe_vm_bind to - * asynchronously bind the buffer `data` at address `BIND_ADDRESS` to - * illustrate `userptr`. It can be synchronized by using the example - * provided for @drm_xe_sync. - * - * .. code-block:: C - * - * data = aligned_alloc(ALIGNMENT, BO_SIZE); - * struct drm_xe_vm_bind bind = { - * .vm_id = vm, - * .num_binds = 1, - * .bind.obj = 0, - * .bind.obj_offset = to_user_pointer(data), - * .bind.range = BO_SIZE, - * .bind.addr = BIND_ADDRESS, - * .bind.op = DRM_XE_VM_BIND_OP_MAP_USERPTR, - * .bind.flags = 0, - * .num_syncs = 1, - * .syncs = &sync, - * .exec_queue_id = 0, - * }; - * ioctl(fd, DRM_IOCTL_XE_VM_BIND, &bind); - * - */ -struct drm_xe_vm_bind { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @vm_id: The ID of the VM to bind to */ - __u32 vm_id; - - /** - * @exec_queue_id: exec_queue_id, must be of class DRM_XE_ENGINE_CLASS_VM_BIND - * and exec queue must have same vm_id. If zero, the default VM bind engine - * is used. - */ - __u32 exec_queue_id; - - /** @pad: MBZ */ - __u32 pad; - - /** @num_binds: number of binds in this IOCTL */ - __u32 num_binds; - - union { - /** @bind: used if num_binds == 1 */ - struct drm_xe_vm_bind_op bind; - - /** - * @vector_of_binds: userptr to array of struct - * drm_xe_vm_bind_op if num_binds > 1 - */ - __u64 vector_of_binds; - }; - - /** @pad2: MBZ */ - __u32 pad2; - - /** @num_syncs: amount of syncs to wait on */ - __u32 num_syncs; - - /** @syncs: pointer to struct drm_xe_sync array */ - __u64 syncs; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_exec_queue_create - Input of &DRM_IOCTL_XE_EXEC_QUEUE_CREATE - * - * The example below shows how to use @drm_xe_exec_queue_create to create - * a simple exec_queue (no parallel submission) of class - * &DRM_XE_ENGINE_CLASS_RENDER. - * - * .. code-block:: C - * - * struct drm_xe_engine_class_instance instance = { - * .engine_class = DRM_XE_ENGINE_CLASS_RENDER, - * }; - * struct drm_xe_exec_queue_create exec_queue_create = { - * .extensions = 0, - * .vm_id = vm, - * .num_bb_per_exec = 1, - * .num_eng_per_bb = 1, - * .instances = to_user_pointer(&instance), - * }; - * ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_CREATE, &exec_queue_create); - * - */ -struct drm_xe_exec_queue_create { -#define DRM_XE_EXEC_QUEUE_EXTENSION_SET_PROPERTY 0 -#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_PRIORITY 0 -#define DRM_XE_EXEC_QUEUE_SET_PROPERTY_TIMESLICE 1 - - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @width: submission width (number BB per exec) for this exec queue */ - __u16 width; - - /** @num_placements: number of valid placements for this exec queue */ - __u16 num_placements; - - /** @vm_id: VM to use for this exec queue */ - __u32 vm_id; - - /** @flags: MBZ */ - __u32 flags; - - /** @exec_queue_id: Returned exec queue ID */ - __u32 exec_queue_id; - - /** - * @instances: user pointer to a 2-d array of struct - * drm_xe_engine_class_instance - * - * length = width (i) * num_placements (j) - * index = j + i * width - */ - __u64 instances; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_exec_queue_destroy - Input of &DRM_IOCTL_XE_EXEC_QUEUE_DESTROY - */ -struct drm_xe_exec_queue_destroy { - /** @exec_queue_id: Exec queue ID */ - __u32 exec_queue_id; - - /** @pad: MBZ */ - __u32 pad; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_exec_queue_get_property - Input of &DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY - * - * The @property can be: - * - %DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN - */ -struct drm_xe_exec_queue_get_property { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @exec_queue_id: Exec queue ID */ - __u32 exec_queue_id; - -#define DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN 0 - /** @property: property to get */ - __u32 property; - - /** @value: property value */ - __u64 value; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_sync - sync object - * - * The @type can be: - * - %DRM_XE_SYNC_TYPE_SYNCOBJ - * - %DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ - * - %DRM_XE_SYNC_TYPE_USER_FENCE - * - * and the @flags can be: - * - %DRM_XE_SYNC_FLAG_SIGNAL - * - * A minimal use of @drm_xe_sync looks like this: - * - * .. code-block:: C - * - * struct drm_xe_sync sync = { - * .flags = DRM_XE_SYNC_FLAG_SIGNAL, - * .type = DRM_XE_SYNC_TYPE_SYNCOBJ, - * }; - * struct drm_syncobj_create syncobj_create = { 0 }; - * ioctl(fd, DRM_IOCTL_SYNCOBJ_CREATE, &syncobj_create); - * sync.handle = syncobj_create.handle; - * ... - * use of &sync in drm_xe_exec or drm_xe_vm_bind - * ... - * struct drm_syncobj_wait wait = { - * .handles = &sync.handle, - * .timeout_nsec = INT64_MAX, - * .count_handles = 1, - * .flags = 0, - * .first_signaled = 0, - * .pad = 0, - * }; - * ioctl(fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait); - */ -struct drm_xe_sync { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - -#define DRM_XE_SYNC_TYPE_SYNCOBJ 0x0 -#define DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ 0x1 -#define DRM_XE_SYNC_TYPE_USER_FENCE 0x2 - /** @type: Type of the this sync object */ - __u32 type; - -#define DRM_XE_SYNC_FLAG_SIGNAL (1 << 0) - /** @flags: Sync Flags */ - __u32 flags; - - union { - /** @handle: Handle for the object */ - __u32 handle; - - /** - * @addr: Address of user fence. When sync is passed in via exec - * IOCTL this is a GPU address in the VM. When sync passed in via - * VM bind IOCTL this is a user pointer. In either case, it is - * the users responsibility that this address is present and - * mapped when the user fence is signalled. Must be qword - * aligned. - */ - __u64 addr; - }; - - /** - * @timeline_value: Input for the timeline sync object. Needs to be - * different than 0 when used with %DRM_XE_SYNC_FLAG_TIMELINE_SYNCOBJ. - */ - __u64 timeline_value; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_exec - Input of &DRM_IOCTL_XE_EXEC - * - * This is an example to use @drm_xe_exec for execution of the object - * at BIND_ADDRESS (see example in @drm_xe_vm_bind) by an exec_queue - * (see example in @drm_xe_exec_queue_create). It can be synchronized - * by using the example provided for @drm_xe_sync. - * - * .. code-block:: C - * - * struct drm_xe_exec exec = { - * .exec_queue_id = exec_queue, - * .syncs = &sync, - * .num_syncs = 1, - * .address = BIND_ADDRESS, - * .num_batch_buffer = 1, - * }; - * ioctl(fd, DRM_IOCTL_XE_EXEC, &exec); - * - */ -struct drm_xe_exec { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** @exec_queue_id: Exec queue ID for the batch buffer */ - __u32 exec_queue_id; - - /** @num_syncs: Amount of struct drm_xe_sync in array. */ - __u32 num_syncs; - - /** @syncs: Pointer to struct drm_xe_sync array. */ - __u64 syncs; - - /** - * @address: address of batch buffer if num_batch_buffer == 1 or an - * array of batch buffer addresses - */ - __u64 address; - - /** - * @num_batch_buffer: number of batch buffer in this exec, must match - * the width of the engine - */ - __u16 num_batch_buffer; - - /** @pad: MBZ */ - __u16 pad[3]; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -/** - * struct drm_xe_wait_user_fence - Input of &DRM_IOCTL_XE_WAIT_USER_FENCE - * - * Wait on user fence, XE will wake-up on every HW engine interrupt in the - * instances list and check if user fence is complete:: - * - * (*addr & MASK) OP (VALUE & MASK) - * - * Returns to user on user fence completion or timeout. - * - * The @op can be: - * - %DRM_XE_UFENCE_WAIT_OP_EQ - * - %DRM_XE_UFENCE_WAIT_OP_NEQ - * - %DRM_XE_UFENCE_WAIT_OP_GT - * - %DRM_XE_UFENCE_WAIT_OP_GTE - * - %DRM_XE_UFENCE_WAIT_OP_LT - * - %DRM_XE_UFENCE_WAIT_OP_LTE - * - * and the @flags can be: - * - %DRM_XE_UFENCE_WAIT_FLAG_ABSTIME - * - %DRM_XE_UFENCE_WAIT_FLAG_SOFT_OP - * - * The @mask values can be for example: - * - 0xffu for u8 - * - 0xffffu for u16 - * - 0xffffffffu for u32 - * - 0xffffffffffffffffu for u64 - */ -struct drm_xe_wait_user_fence { - /** @extensions: Pointer to the first extension struct, if any */ - __u64 extensions; - - /** - * @addr: user pointer address to wait on, must qword aligned - */ - __u64 addr; - -#define DRM_XE_UFENCE_WAIT_OP_EQ 0x0 -#define DRM_XE_UFENCE_WAIT_OP_NEQ 0x1 -#define DRM_XE_UFENCE_WAIT_OP_GT 0x2 -#define DRM_XE_UFENCE_WAIT_OP_GTE 0x3 -#define DRM_XE_UFENCE_WAIT_OP_LT 0x4 -#define DRM_XE_UFENCE_WAIT_OP_LTE 0x5 - /** @op: wait operation (type of comparison) */ - __u16 op; - -#define DRM_XE_UFENCE_WAIT_FLAG_ABSTIME (1 << 0) - /** @flags: wait flags */ - __u16 flags; - - /** @pad: MBZ */ - __u32 pad; - - /** @value: compare value */ - __u64 value; - - /** @mask: comparison mask */ - __u64 mask; - - /** - * @timeout: how long to wait before bailing, value in nanoseconds. - * Without DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flag set (relative timeout) - * it contains timeout expressed in nanoseconds to wait (fence will - * expire at now() + timeout). - * When DRM_XE_UFENCE_WAIT_FLAG_ABSTIME flat is set (absolute timeout) wait - * will end at timeout (uses system MONOTONIC_CLOCK). - * Passing negative timeout leads to neverending wait. - * - * On relative timeout this value is updated with timeout left - * (for restarting the call in case of signal delivery). - * On absolute timeout this value stays intact (restarted call still - * expire at the same point of time). - */ - __s64 timeout; - - /** @exec_queue_id: exec_queue_id returned from xe_exec_queue_create_ioctl */ - __u32 exec_queue_id; - - /** @pad2: MBZ */ - __u32 pad2; - - /** @reserved: Reserved */ - __u64 reserved[2]; -}; - -#if defined(__cplusplus) -} -#endif - -#endif /* _XE_DRM_H_ */ From f8fa3f8ea65035b86a4391f78679cf2255960ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Sep 2024 10:39:32 +0800 Subject: [PATCH 58/65] Scripts: add SPDX-License-Identifier --- scripts/gen-pciids.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/gen-pciids.py b/scripts/gen-pciids.py index 6c30fb735..80e7304fb 100644 --- a/scripts/gen-pciids.py +++ b/scripts/gen-pciids.py @@ -32,6 +32,10 @@ def main(keep_vendor_list: set): vendors[-1].devices.append(PciDeviceModel(int(id, 16), name)) code = """\ +// SPDX-License-Identifier: BSD-3-Clause +// https://opensource.org/license/BSD-3-Clause +// Generated from https://pci-ids.ucw.cz/v2.2/pci.ids + #include #include From acd5d4a2589c910c9eca6bd75de95852d549b863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Sep 2024 10:40:21 +0800 Subject: [PATCH 59/65] Release: v2.26.0 --- CHANGELOG.md | 25 +++++++++++++++++++++++++ CMakeLists.txt | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ab26cd0e..4f8310422 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +# 2.26.0 + +Features: +* Detect GPU index (#1267, GPU) +* Count Flatpak runtime packages (#1085, Packages, Linux) +* Support pacstall package manager (Packages, Linux) +* Support CU core count, max frequency, VMEM usage detection for AMD cards on Linux (GPU, Linux) + * Requires `--gpu-driver-specific` +* Support EU core count, VMEM size detection Intel cards on Linux (GPU, Linux) + * Requires `--gpu-driver-specific`. VMEM usage detection requires root permissions. +* Add new module `TPM` to print TPM (Trusted Platform Module) version if available (TPM) +* Support GPU driver version detection (GPU, macOS) +* Add new CMake option `-DENABLE_EMBEDDED_PCIIDS=ON`. + * If enabled, fastfetch will download the newest [`pci.ids`](https://pci-ids.ucw.cz/) file, [transform it into C code](https://github.com/fastfetch-cli/fastfetch/blob/dev/scripts/gen-pciids.py) and compile it into fastfetch binaries. + +Bugfixes: +* Fix font size detecton of foot terminal (#1276, TerminalFont, Linux) +* Ignore `su` and `sudo` when detecting terminal (#1283, Terminal, Linux) +* Always print inches in integer (Display) +* Fix Wifi connection protocol detection on macOS Sequoia (Wifi, macOS) +* Fix hanging when font name is long when detecting kitty term font (#1289, TerminalFont) + +Logos: +* Add FoxOS + # 2.25.0 Features: diff --git a/CMakeLists.txt b/CMakeLists.txt index dd98838d3..3f0a50900 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url project(fastfetch - VERSION 2.25.0 + VERSION 2.26.0 LANGUAGES C DESCRIPTION "Fast neofetch-like system information tool" HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch" From a424839d2f07029eca7deeadea25afcbebc1a902 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sat, 28 Sep 2024 16:49:03 +0800 Subject: [PATCH 60/65] CPU (Linux): remove `bios_limit` detection --- CHANGELOG.md | 3 +++ src/detection/cpu/cpu.h | 1 - src/detection/cpu/cpu_linux.c | 23 +++++++++++++++-------- src/modules/cpu/cpu.c | 13 ++----------- src/modules/loadavg/loadavg.c | 1 - 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f8310422..961b465f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # 2.26.0 +Changes: +* To be consistent to other platforms, CPU frequency detection on Linux no longer checks `bios_limit` + Features: * Detect GPU index (#1267, GPU) * Count Flatpak runtime packages (#1085, Packages, Linux) diff --git a/src/detection/cpu/cpu.h b/src/detection/cpu/cpu.h index 9ddc00300..eb5bd90f4 100644 --- a/src/detection/cpu/cpu.h +++ b/src/detection/cpu/cpu.h @@ -21,7 +21,6 @@ typedef struct FFCPUResult uint32_t frequencyBase; // GHz uint32_t frequencyMax; // GHz - uint32_t frequencyBiosLimit; // GHz FFCPUCore coreTypes[16]; // number of P cores, E cores, etc. diff --git a/src/detection/cpu/cpu_linux.c b/src/detection/cpu/cpu_linux.c index 541ac91d9..ffc6d835d 100644 --- a/src/detection/cpu/cpu_linux.c +++ b/src/detection/cpu/cpu_linux.c @@ -325,18 +325,25 @@ static bool detectFrequency(FFCPUResult* cpu, const FFCPUOptions* options) if (ffStrStartsWith(entry->d_name, "policy") && ffCharIsDigit(entry->d_name[strlen("policy")])) { ffStrbufAppendS(&path, entry->d_name); + + uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer); + if (fmax == 0) continue; + + if (cpu->frequencyMax >= fmax) + { + if (!options->showPeCoreCount) + { + ffStrbufSubstrBefore(&path, baseLen); + continue; + } + } + else + cpu->frequencyMax = fmax; + uint32_t fbase = getFrequency(&path, "/base_frequency", NULL, &buffer); if (fbase > 0) cpu->frequencyBase = cpu->frequencyBase > fbase ? cpu->frequencyBase : fbase; - uint32_t fbioslimit = getFrequency(&path, "/bios_limit", NULL, &buffer); - if (fbioslimit > 0) - cpu->frequencyBiosLimit = cpu->frequencyBiosLimit > fbioslimit ? cpu->frequencyBiosLimit : fbioslimit; - - uint32_t fmax = getFrequency(&path, "/cpuinfo_max_freq", "/scaling_max_freq", &buffer); - if (fmax > 0) - cpu->frequencyMax = cpu->frequencyMax > fmax ? cpu->frequencyMax : fmax; - if (options->showPeCoreCount) { uint32_t freq = fbase == 0 ? fmax : fbase; // seems base frequencies are more stable diff --git a/src/modules/cpu/cpu.c b/src/modules/cpu/cpu.c index 6bf2de570..0381b32f4 100644 --- a/src/modules/cpu/cpu.c +++ b/src/modules/cpu/cpu.c @@ -6,7 +6,7 @@ #include "modules/cpu/cpu.h" #include "util/stringUtils.h" -#define FF_CPU_NUM_FORMAT_ARGS 10 +#define FF_CPU_NUM_FORMAT_ARGS 9 static int sortCores(const FFCPUCore* a, const FFCPUCore* b) { @@ -19,7 +19,6 @@ void ffPrintCPU(FFCPUOptions* options) .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -71,9 +70,7 @@ void ffPrintCPU(FFCPUOptions* options) else if(cpu.coresOnline > 1) ffStrbufAppendF(&str, " (%u)", cpu.coresOnline); - uint32_t freq = cpu.frequencyBiosLimit; - if(freq == 0) - freq = cpu.frequencyMax; + uint32_t freq = cpu.frequencyMax; if(freq == 0) freq = cpu.frequencyBase; if(freq > 0) @@ -96,8 +93,6 @@ void ffPrintCPU(FFCPUOptions* options) ffParseFrequency(cpu.frequencyBase, &freqBase); FF_STRBUF_AUTO_DESTROY freqMax = ffStrbufCreate(); ffParseFrequency(cpu.frequencyMax, &freqMax); - FF_STRBUF_AUTO_DESTROY freqBioslimit = ffStrbufCreate(); - ffParseFrequency(cpu.frequencyBiosLimit, &freqBioslimit); FF_STRBUF_AUTO_DESTROY tempStr = ffStrbufCreate(); ffTempsAppendNum(cpu.temperature, &tempStr, options->tempConfig, &options->moduleArgs); @@ -111,7 +106,6 @@ void ffPrintCPU(FFCPUOptions* options) FF_FORMAT_ARG(freqMax, "freq-max"), FF_FORMAT_ARG(tempStr, "temperature"), FF_FORMAT_ARG(coreTypes, "core-types"), - FF_FORMAT_ARG(freqBioslimit, "freq-bios-limit"), })); } } @@ -190,7 +184,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; @@ -219,7 +212,6 @@ void ffGenerateCPUJsonResult(FFCPUOptions* options, yyjson_mut_doc* doc, yyjson_ yyjson_mut_val* frequency = yyjson_mut_obj_add_obj(doc, obj, "frequency"); yyjson_mut_obj_add_uint(doc, frequency, "base", cpu.frequencyBase); yyjson_mut_obj_add_uint(doc, frequency, "max", cpu.frequencyMax); - yyjson_mut_obj_add_uint(doc, frequency, "biosLimit", cpu.frequencyBiosLimit); yyjson_mut_val* coreTypes = yyjson_mut_obj_add_arr(doc, obj, "coreTypes"); for (uint32_t i = 0; i < sizeof (cpu.coreTypes) / sizeof (cpu.coreTypes[0]) && cpu.coreTypes[i].count > 0; i++) @@ -248,7 +240,6 @@ void ffPrintCPUHelpFormat(void) "Max frequency (formatted) - freq-max", "Temperature (formatted) - temperature", "Logical core count grouped by frequency - core-types", - "Bios limited frequency (formatted) - freq-bios-limit", })); } diff --git a/src/modules/loadavg/loadavg.c b/src/modules/loadavg/loadavg.c index 7802c3fd2..d53b12ff4 100644 --- a/src/modules/loadavg/loadavg.c +++ b/src/modules/loadavg/loadavg.c @@ -32,7 +32,6 @@ void ffPrintLoadavg(FFLoadavgOptions* options) .temperature = FF_CPU_TEMP_UNSET, .frequencyMax = 0, .frequencyBase = 0, - .frequencyBiosLimit = 0, .name = ffStrbufCreate(), .vendor = ffStrbufCreate(), }; From 140b9834cc453388ef15cdd53bc3c813b947ab94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sat, 28 Sep 2024 23:06:43 +0800 Subject: [PATCH 61/65] Logo (Builtin): add GXDE OS Fix #1300 --- CHANGELOG.md | 1 + src/logo/ascii/deepin.txt | 2 +- src/logo/builtin.c | 10 ++++++++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 961b465f1..4ec159604 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Bugfixes: Logos: * Add FoxOS +* Add GXDE OS # 2.25.0 diff --git a/src/logo/ascii/deepin.txt b/src/logo/ascii/deepin.txt index d79eaa42f..f28458c67 100644 --- a/src/logo/ascii/deepin.txt +++ b/src/logo/ascii/deepin.txt @@ -1,4 +1,4 @@ -$1 ............ + ............ .';;;;;. .,;,. .,;;;;;;;. ';;;;;;;. .;::::::::' .,::;;,''''',. diff --git a/src/logo/builtin.c b/src/logo/builtin.c index 1fd6d86be..62f8291ca 100644 --- a/src/logo/builtin.c +++ b/src/logo/builtin.c @@ -1922,6 +1922,16 @@ static const FFlogo G[] = { .colorKeys = FF_COLOR_FG_YELLOW, .colorTitle = FF_COLOR_FG_WHITE, }, + // GXDE + { + .names = {"GXDE"}, + .lines = FASTFETCH_DATATEXT_LOGO_DEEPIN, + .colors = { + FF_COLOR_FG_RED, + }, + .colorKeys = FF_COLOR_FG_RED, + .colorTitle = FF_COLOR_FG_RED, + }, // LAST {}, }; From 51796de69ad15abdbd8b8659a04548a38ccab4be Mon Sep 17 00:00:00 2001 From: Ziyao Date: Sun, 29 Sep 2024 02:23:20 +0000 Subject: [PATCH 62/65] Display (Linux): detect all enabled or connected connectors (#1301) DRM connectors have two properties, "enabled" and "status", standing for "enabled by userspace" and "a display has been connected". Connector status cannot be reliably detected sometimes, in this case status will be set to unknown and it is still okay to enable it. Some drivers are also able to enable disconnected connectors. So it is both meaningful to detect connectors in two states, - An enabled connector, where it must have been operating in some configuration required by userspace - A connected connector, where driver is sure a display has been connected to the port, this is the obvious case. In the original implementation, only information of connected connectors are detected and an enabled connector without hotplug detection capability, like a Composite video connector, will be silently ignored. Switch to the new strategy to detect these connectors correctly. References: https://github.com/torvalds/linux/blob/3efc57369a0ce8f76bf0804f7e673982384e4ac9/include/drm/drm_connector.h#L58-L89 Signed-off-by: Yao Zi --- src/detection/displayserver/linux/drm.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index 1533b4990..ca168259e 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -28,13 +28,19 @@ static const char* drmParseSysfs(FFDisplayServerResult* result) ffStrbufAppendS(&drmDir, entry->d_name); uint32_t drmDirWithDnameLength = drmDir.length; - ffStrbufAppendS(&drmDir, "/status"); - char status = 'd'; // disconnected - ffReadFileData(drmDir.chars, sizeof(status), &status); - if (status != 'c') // connected - { + char buf; + ffStrbufAppendS(&drmDir, "/enabled"); + if (!ffReadFileData(drmDir.chars, sizeof(buf), &buf) || buf != 'e') { + /* read failed or enabled != "enabled" */ + ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength); + ffStrbufAppendS(&drmDir, "/status"); + buf = 'd'; + ffReadFileData(drmDir.chars, sizeof(buf), &buf); + if (buf != 'c') { + /* read failed or status != "connected" */ ffStrbufSubstrBefore(&drmDir, drmDirLength); continue; + } } unsigned width = 0, height = 0, physicalWidth = 0, physicalHeight = 0; From 5381395c54304337783722b93abdf4606c56715b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Sep 2024 09:05:22 +0800 Subject: [PATCH 63/65] GPU (macOS): update how integrated GPUs are detected --- src/detection/gpu/gpu_apple.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/gpu/gpu_apple.m b/src/detection/gpu/gpu_apple.m index 3719760fd..95e4c3058 100644 --- a/src/detection/gpu/gpu_apple.m +++ b/src/detection/gpu/gpu_apple.m @@ -65,7 +65,7 @@ const char* ffGpuDetectMetal(FFlist* gpus) else if ([device supportsFamily:MTLGPUFamilyCommon1]) ffStrbufSetStatic(&gpu->platformApi, "Metal Common 1"); - gpu->type = device.hasUnifiedMemory ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; + gpu->type = device.location == MTLDeviceLocationBuiltIn ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE; gpu->index = (uint32_t) device.locationNumber; #endif } From 88097463afc5e3396041edfb46b879ae3c91963f Mon Sep 17 00:00:00 2001 From: Carter Li Date: Sun, 29 Sep 2024 10:25:46 +0800 Subject: [PATCH 64/65] Display (Linux): report displays of unknown connection state too Ref: #1301 --- src/detection/displayserver/linux/drm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/detection/displayserver/linux/drm.c b/src/detection/displayserver/linux/drm.c index ca168259e..48949266d 100644 --- a/src/detection/displayserver/linux/drm.c +++ b/src/detection/displayserver/linux/drm.c @@ -257,7 +257,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result) if (!conn) continue; - if (conn->connection == DRM_MODE_CONNECTED) + if (conn->connection != DRM_MODE_DISCONNECTED) { drmModeEncoder* encoder = ffdrmModeGetEncoder(fd, conn->encoder_id); uint32_t width = 0, height = 0, refreshRate = 0; From 17c9179b7d323288c59ed16401f41d101e5b551b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Sun, 29 Sep 2024 10:29:11 +0800 Subject: [PATCH 65/65] Doc: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ec159604..ad1c1ae88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ Bugfixes: * Always print inches in integer (Display) * Fix Wifi connection protocol detection on macOS Sequoia (Wifi, macOS) * Fix hanging when font name is long when detecting kitty term font (#1289, TerminalFont) +* Detect all enabled or connected connectors (#1301, Display, Linux) Logos: * Add FoxOS