diff --git a/Makefile b/Makefile index c9a2c36..35e9297 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,8 @@ PREFIX ?= /usr SRC_COMMON=src/common/ -COMMON_SRC = $(SRC_COMMON)main.c $(SRC_COMMON)cpu.c $(SRC_COMMON)udev.c $(SRC_COMMON)printer.c $(SRC_COMMON)args.c $(SRC_COMMON)global.c -COMMON_HDR = $(SRC_COMMON)ascii.h $(SRC_COMMON)cpu.h $(SRC_COMMON)udev.h $(SRC_COMMON)printer.h $(SRC_COMMON)args.h $(SRC_COMMON)global.h +COMMON_SRC = $(SRC_COMMON)main.c $(SRC_COMMON)cpu.c $(SRC_COMMON)udev.c $(SRC_COMMON)pci.c $(SRC_COMMON)printer.c $(SRC_COMMON)args.c $(SRC_COMMON)global.c +COMMON_HDR = $(SRC_COMMON)ascii.h $(SRC_COMMON)cpu.h $(SRC_COMMON)udev.h $(SRC_COMMON)pci.h $(SRC_COMMON)printer.h $(SRC_COMMON)args.h $(SRC_COMMON)global.h ifneq ($(OS),Windows_NT) GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)" diff --git a/src/arm/soc.c b/src/arm/soc.c index 0399daf..8c1f8ab 100644 --- a/src/arm/soc.c +++ b/src/arm/soc.c @@ -8,6 +8,7 @@ #include "udev.h" #include "uarch.h" #include "../common/global.h" +#include "../common/pci.h" #if defined(__APPLE__) || defined(__MACH__) #include "sysctl.h" @@ -834,6 +835,43 @@ struct system_on_chip* guess_soc_from_uarch(struct system_on_chip* soc, struct c return soc; } +struct system_on_chip* guess_soc_from_pci(struct system_on_chip* soc, struct cpuInfo* cpu) { + struct pci_devices * pci = get_pci_devices(); + if (pci == NULL) { + printWarn("guess_soc_from_pci: Unable to find suitable PCI devices"); + return soc; + } + + typedef struct { + uint16_t vendor_id; + uint16_t device_id; + struct system_on_chip soc; + } pciToSoC; + + pciToSoC socFromPCI[] = { + {PCI_VENDOR_NVIDIA, PCI_DEVICE_TEGRA_X1, {SOC_TEGRA_X1, SOC_VENDOR_NVIDIA, 20, "Tegra X1", NULL} }, + // {PCI_VENDOR_NVIDIA, PCI_DEVICE_GH_200,{SOC_GH_200, SOC_VENDOR_NVIDIA, ?, "Grace Hopper", NULL} }, + {0x0000, 0x0000, {UNKNOWN, SOC_VENDOR_UNKNOWN, -1, "", NULL} } + }; + + int index = 0; + while (socFromPCI[index].vendor_id != 0x0) { + for (int i=0; i < pci->num_devices; i++) { + struct pci_device * dev = pci->devices[i]; + + if (socFromPCI[index].vendor_id == dev->vendor_id && + socFromPCI[index].device_id == dev->device_id) { + fill_soc(soc, socFromPCI[index].soc.soc_name, socFromPCI[index].soc.soc_model, socFromPCI[index].soc.process); + return soc; + } + } + index++; + } + + printWarn("guess_soc_from_pci: No PCI device matched the list"); + return soc; +} + int hex2int(char c) { if (c >= '0' && c <= '9') return c - '0'; @@ -1004,14 +1042,18 @@ struct system_on_chip* get_soc(struct cpuInfo* cpu) { printWarn("SoC detection failed using Android: Found '%s' string", soc->raw_name); } #endif // ifdef __ANDROID__ - // If cpufinfo/Android (if available) detection fails, try with nvmem + // If previous steps failed, try with nvmem if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) { soc = guess_soc_from_nvmem(soc); } - // If everything else failed, try infering it from the microarchitecture + // If previous steps failed, try infering it from the microarchitecture if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) { soc = guess_soc_from_uarch(soc, cpu); } + // If previous steps failed, try infering it from the pci device id + if(soc->soc_vendor == SOC_VENDOR_UNKNOWN) { + soc = guess_soc_from_pci(soc, cpu); + } } #elif defined __APPLE__ || __MACH__ soc = guess_soc_apple(soc); diff --git a/src/arm/socs.h b/src/arm/socs.h index 4ba1066..d5a3167 100644 --- a/src/arm/socs.h +++ b/src/arm/socs.h @@ -363,6 +363,8 @@ enum { SOC_GOOGLE_TENSOR, SOC_GOOGLE_TENSOR_G2, SOC_GOOGLE_TENSOR_G3, + // NVIDIA, + SOC_TEGRA_X1, // UNKNOWN SOC_MODEL_UNKNOWN }; @@ -378,6 +380,7 @@ inline static VENDOR get_soc_vendor_from_soc(SOC soc) { else if(soc >= SOC_ALLWINNER_A10 && soc <= SOC_ALLWINNER_R328) return SOC_VENDOR_ALLWINNER; else if(soc >= SOC_ROCKCHIP_3288 && soc <= SOC_ROCKCHIP_3588) return SOC_VENDOR_ROCKCHIP; else if(soc >= SOC_GOOGLE_TENSOR && soc <= SOC_GOOGLE_TENSOR_G3) return SOC_VENDOR_GOOGLE; + else if(soc >= SOC_TEGRA_X1 && soc <= SOC_TEGRA_X1) return SOC_VENDOR_NVIDIA; return SOC_VENDOR_UNKNOWN; } diff --git a/src/common/ascii.h b/src/common/ascii.h index bbae1a9..302de8c 100644 --- a/src/common/ascii.h +++ b/src/common/ascii.h @@ -360,6 +360,27 @@ $C1##########@@@@@@@@@@@@@@@@############## \ $C1######################################## \ $C1 #################################### " +#define ASCII_NVIDIA \ +"$C1 'cccccccccccccccccccccccccc \ +$C1 ;oooooooooooooooooooooooool \ +$C1 .:::. .oooooooooooooooooool \ +$C1 .:cll; ,c:::. cooooooooooooool \ +$C1 ,clo' ;. oolc: ooooooooooool \ +$C1.cloo ;cclo . .olc. coooooooool \ +$C1oooo :lo, ;ll; looc :oooooooool \ +$C1 oooc ool. ;oooc;clol :looooooooool \ +$C1 :ooc ,ol; ;oooooo. .cloo; loool \ +$C1 ool; .olc. ,:lool .lool \ +$C1 ool:. ,::::ccloo. :clooool \ +$C1 oolc::. ':cclooooooool \ +$C1 ;oooooooooooooooooooooooool \ +$C1 \ +$C1 \ +$C2######. ## ## ## ###### ## ### \ +$C2## ## ## ## ## ## ## ## #: :# \ +$C2## ## ## ## ## ## ## ## ####### \ +$C2## ## ### ## ###### ## ## ## " + // --------------------- LONG LOGOS ------------------------- // #define ASCII_AMD_L \ "$C1 \ @@ -492,6 +513,23 @@ $C1 ###########. ############ \ $C1 ################ \ $C1 ####### " +#define ASCII_NVIDIA_L \ +"$C1 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM \ +$C1 MMMMMMMMMMMMMMMMMMMMMMMMMMMMMM \ +$C1 .:: 'MMMMMMMMMMMMMMMMMMMMMMMMM \ +$C1 ccllooo;:;. ;MMMMMMMMMMMMMMMMMM \ +$C1 cloc :ooollcc: :MMMMMMMMMMMMMMM \ +$C1 cloc :ccl; lolc, ;MMMMMMMMMMMM \ +$C1.cloo: :clo ;c: .ool; MMMMMMMMMMM \ +$C1 ooo: ooo :ool, .cloo. ;lMMMMMMMMMMM \ +$C1 ooo: ooc :ooooccooo. :MMMM lMMMMMMM \ +$C1 ooc. ool: :oooooo' ,cloo. MMMM \ +$C1 ool:. olc: .:cloo. :MMMM \ +$C1 olc, ;:::cccloo. :MMMMMMMM \ +$C1 olcc::; ,:ccloMMMMMMMMM \ +$C1 :......oMMMMMMMMMMMMMMMMMMMMMM \ +$C1 :lllMMMMMMMMMMMMMMMMMMMMMMMMMM " + typedef struct ascii_logo asciiL; // +-----------------------------------------------------------------------------------------------------------------+ @@ -516,6 +554,7 @@ asciiL logo_riscv = { ASCII_RISCV, 63, 18, false, {C_FG_CYAN, C_FG_Y asciiL logo_sifive = { ASCII_SIFIVE, 48, 19, true, {C_BG_WHITE, C_BG_BLACK}, {C_FG_WHITE, C_FG_BLUE} }; asciiL logo_starfive = { ASCII_STARFIVE, 33, 17, false, {C_FG_WHITE}, {C_FG_WHITE, C_FG_BLUE} }; asciiL logo_sipeed = { ASCII_SIPEED, 41, 16, true, {C_BG_RED, C_BG_WHITE}, {C_FG_RED, C_FG_WHITE} }; +asciiL logo_nvidia = { ASCII_NVIDIA, 45, 19, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; // Long variants | ----------------------------------------------------------------------------------------------------------------| asciiL logo_amd_l = { ASCII_AMD_L, 62, 19, true, {C_BG_WHITE, C_BG_GREEN}, {C_FG_WHITE, C_FG_GREEN} }; @@ -525,6 +564,7 @@ asciiL logo_arm_l = { ASCII_ARM_L, 60, 8, true, {C_BG_CYAN}, asciiL logo_ibm_l = { ASCII_IBM_L, 62, 13, true, {C_BG_CYAN, C_FG_WHITE}, {C_FG_CYAN, C_FG_WHITE} }; asciiL logo_starfive_l = { ASCII_STARFIVE_L, 50, 22, false, {C_FG_WHITE}, {C_FG_WHITE, C_FG_BLUE} }; asciiL logo_sifive_l = { ASCII_SIFIVE_L, 53, 21, true, {C_BG_WHITE, C_BG_BLACK}, {C_FG_WHITE, C_FG_CYAN} }; +asciiL logo_nvidia_l = { ASCII_NVIDIA_L, 50, 15, false, {C_FG_GREEN, C_FG_WHITE}, {C_FG_WHITE, C_FG_GREEN} }; asciiL logo_unknown = { NULL, 0, 0, false, {COLOR_NONE}, {COLOR_NONE, COLOR_NONE} }; #endif diff --git a/src/common/pci.c b/src/common/pci.c new file mode 100644 index 0000000..64b068b --- /dev/null +++ b/src/common/pci.c @@ -0,0 +1,169 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "udev.h" +#include "global.h" +#include "pci.h" + +// TODO: Linux only +// TODO: Only neccesary headers (dont remove limits) + +#ifndef PATH_MAX + #define PATH_MAX 1024 +#endif + +#define PCI_PATH "/sys/bus/pci/devices/" +#define MAX_LENGTH_PCI_DIR_NAME 1024 + +/* + * doc: https://wiki.osdev.org/PCI#Class_Codes + * https://pci-ids.ucw.cz/read/PC + */ +#define PCI_VENDOR_ID_AMD 0x1002 +#define CLASS_VGA_CONTROLLER 0x0300 +#define CLASS_3D_CONTROLLER 0x0302 + +struct pci_devices * get_pci_paths(void) { + DIR *dfd; + + if ((dfd = opendir(PCI_PATH)) == NULL) { + perror("opendir"); + return false; + } + + struct dirent *dp; + int numDirs = 0; + + // TODO: error? readdir + while ((dp = readdir(dfd)) != NULL) { + if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) + numDirs++; + } + + rewinddir(dfd); + + // char ** pciDirs = emalloc(numDirs * sizeof(char *)); + struct pci_devices * pci = emalloc(sizeof(struct pci_devices)); + pci->num_devices = numDirs; + pci->devices = emalloc(sizeof(struct pci_device) * pci->num_devices); + char * full_path = emalloc(PATH_MAX * sizeof(char *)); + struct stat stbuf; + int i = 0; + + while ((dp = readdir(dfd)) != NULL) { + if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) + continue; + + if (strlen(dp->d_name) > MAX_LENGTH_PCI_DIR_NAME) { + printErr("Directory name is too long: %s", dp->d_name); + return false; + } + + memset(full_path, 0, PATH_MAX * sizeof(char *)); + snprintf(full_path, min(strlen(PCI_PATH) + strlen(dp->d_name) + 1, PATH_MAX), "%s%s", PCI_PATH, dp->d_name); + + if (stat(full_path, &stbuf ) == -1) { + perror("stat"); + return false; + } + + if ((stbuf.st_mode & S_IFMT ) == S_IFDIR) { + int strLen = min(MAX_LENGTH_PCI_DIR_NAME, strlen(dp->d_name)) + 1; + pci->devices[i] = emalloc(sizeof(struct pci_device)); + pci->devices[i]->path = ecalloc(sizeof(char), strLen); + strncpy(pci->devices[i]->path, dp->d_name, strLen); + i++; + } + } + + return pci; +} + +void populate_pci_devices(struct pci_devices * pci) { + int filelen; + char* buf; + + for (int i=0; i < pci->num_devices; i++) { + struct pci_device* dev = pci->devices[i]; + int path_size = strlen(PCI_PATH) + strlen(dev->path) + 3; + + // Read vendor_id + char *vendor_id_path = emalloc(sizeof(char) * (path_size + strlen("vendor"))); + sprintf(vendor_id_path, "%s/%s/%s", PCI_PATH, dev->path, "vendor"); + + if ((buf = read_file(vendor_id_path, &filelen)) == NULL) { + printWarn("read_file: %s: %s\n", vendor_id_path, strerror(errno)); + dev->vendor_id = 0; + } + else { + dev->vendor_id = strtol(buf, NULL, 16); + } + + // Read device_id + char *device_id_path = emalloc(sizeof(char) * (path_size + strlen("device"))); + sprintf(device_id_path, "%s/%s/%s", PCI_PATH, dev->path, "device"); + if ((buf = read_file(device_id_path, &filelen)) == NULL) { + printWarn("read_file: %s: %s\n", device_id_path, strerror(errno)); + dev->device_id = 0; + } + else { + dev->device_id = strtol(buf, NULL, 16); + } + } +} + +// Filter the input in order to get only those PCI devices which +// we are interested in (i.e., which vendor is NVIDIA), and return +// the filtered result. +struct pci_devices * filter_pci_devices(struct pci_devices * pci) { + int * devices_to_get = emalloc(sizeof(int) * pci->num_devices); + int dev_ptr = 0; + + for (int i=0; i < pci->num_devices; i++) { + if (pci->devices[i]->vendor_id == PCI_VENDOR_NVIDIA) { + devices_to_get[dev_ptr] = i; + dev_ptr++; + } + } + + struct pci_devices * pci_filtered = emalloc(sizeof(struct pci_devices)); + pci_filtered->num_devices = dev_ptr; + if (pci_filtered->num_devices == 0) + pci_filtered->devices = NULL; + else + pci_filtered->devices = emalloc(sizeof(struct pci_device) * pci_filtered->num_devices); + + for (int i=0; i < dev_ptr; i++) { + pci_filtered->devices[i] = pci->devices[devices_to_get[i]]; + } + + return pci_filtered; +} + +struct pci_devices * get_pci_devices(void) { + struct pci_devices * pci = get_pci_paths(); + + if (pci == NULL) + return false; + + populate_pci_devices(pci); + + struct pci_devices * filtered = filter_pci_devices(pci); + + return filtered; +} \ No newline at end of file diff --git a/src/common/pci.h b/src/common/pci.h new file mode 100644 index 0000000..b8ad0b2 --- /dev/null +++ b/src/common/pci.h @@ -0,0 +1,20 @@ +#ifndef __PCI__ +#define __PCI__ + +#define PCI_VENDOR_NVIDIA 0x10de +#define PCI_DEVICE_TEGRA_X1 0x0faf + +struct pci_device { + char * path; + uint16_t vendor_id; + uint16_t device_id; +}; + +struct pci_devices { + struct pci_device ** devices; + int num_devices; +}; + +struct pci_devices * get_pci_devices(void); + +#endif \ No newline at end of file diff --git a/src/common/printer.c b/src/common/printer.c index 8181108..1a43e5f 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -383,6 +383,8 @@ void choose_ascii_art(struct ascii* art, struct color** cs, struct terminal* ter art->art = &logo_allwinner; else if(art->vendor == SOC_VENDOR_ROCKCHIP) art->art = &logo_rockchip; + else if(art->vendor == SOC_VENDOR_NVIDIA) + art->art = choose_ascii_art_aux(&logo_nvidia_l, &logo_nvidia, term, lf); else { art->art = choose_ascii_art_aux(&logo_arm_l, &logo_arm, term, lf); } diff --git a/src/common/soc.c b/src/common/soc.c index 2837d27..2211f50 100644 --- a/src/common/soc.c +++ b/src/common/soc.c @@ -20,6 +20,7 @@ static char* soc_trademark_string[] = { [SOC_VENDOR_APPLE] = "Apple ", [SOC_VENDOR_ROCKCHIP] = "Rockchip ", [SOC_VENDOR_GOOGLE] = "Google ", + [SOC_VENDOR_NVIDIA] = "NVIDIA ", // RISC-V [SOC_VENDOR_SIFIVE] = "SiFive ", [SOC_VENDOR_STARFIVE] = "StarFive ", diff --git a/src/common/soc.h b/src/common/soc.h index 7544984..2d4fcf7 100644 --- a/src/common/soc.h +++ b/src/common/soc.h @@ -24,6 +24,7 @@ enum { SOC_VENDOR_APPLE, SOC_VENDOR_ROCKCHIP, SOC_VENDOR_GOOGLE, + SOC_VENDOR_NVIDIA, // RISC-V SOC_VENDOR_SIFIVE, SOC_VENDOR_STARFIVE,