GPU: embed pci.ids into fastfetch

This commit is contained in:
李通洲 2024-09-25 16:41:55 +08:00 committed by Carter Li
parent ae6817e106
commit 96d885e93a
8 changed files with 191 additions and 38 deletions

View File

@ -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"

89
scripts/gen-pciids.py Normal file
View File

@ -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 <stdint.h>
#include <stddef.h>
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 <src/detection/gpu/gpu.c>
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
})

View File

@ -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);
}

View File

@ -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

View File

@ -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))

View File

@ -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);

View File

@ -1,15 +1,21 @@
#include "gpu.h"
#include "common/io/io.h"
#include <stdlib.h>
#ifdef __FreeBSD__
#include <paths.h>
#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);
}

View File

@ -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);
}
}