diff --git a/Makefile b/Makefile index 35e9297..4ce178f 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)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 +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 ifneq ($(OS),Windows_NT) GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)" @@ -32,8 +32,8 @@ ifneq ($(OS),Windows_NT) CFLAGS += -DARCH_PPC -std=gnu99 -fstack-protector-all -Wno-language-extension-token else ifeq ($(arch), $(filter $(arch), arm aarch64_be aarch64 arm64 armv8b armv8l armv7l armv6l)) SRC_DIR=src/arm/ - SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_COMMON)soc.c $(SRC_DIR)soc.c $(SRC_DIR)udev.c - HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_COMMON)soc.h $(SRC_DIR)soc.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h + SOURCE += $(COMMON_SRC) $(SRC_DIR)midr.c $(SRC_DIR)uarch.c $(SRC_COMMON)soc.c $(SRC_DIR)soc.c $(SRC_COMMON)pci.c $(SRC_DIR)udev.c + HEADERS += $(COMMON_HDR) $(SRC_DIR)midr.h $(SRC_DIR)uarch.h $(SRC_COMMON)soc.h $(SRC_DIR)soc.h $(SRC_COMMON)pci.h $(SRC_DIR)udev.c $(SRC_DIR)socs.h CFLAGS += -DARCH_ARM -Wno-unused-parameter -std=c99 -fstack-protector-all os := $(shell uname -s) diff --git a/src/common/pci.c b/src/common/pci.c index 64b068b..fd46b2f 100644 --- a/src/common/pci.c +++ b/src/common/pci.c @@ -1,28 +1,12 @@ #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 @@ -38,51 +22,56 @@ #define CLASS_VGA_CONTROLLER 0x0300 #define CLASS_3D_CONTROLLER 0x0302 +// Return a list of PCI devices containing only +// the sysfs path struct pci_devices * get_pci_paths(void) { - DIR *dfd; + DIR *dirp; - if ((dfd = opendir(PCI_PATH)) == NULL) { + if ((dirp = opendir(PCI_PATH)) == NULL) { perror("opendir"); - return false; + return NULL; } struct dirent *dp; - int numDirs = 0; + int numDirs = 0; + errno = 0; - // TODO: error? readdir - while ((dp = readdir(dfd)) != NULL) { + while ((dp = readdir(dirp)) != NULL) { if (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0) numDirs++; + } + if (errno != 0) { + perror("readdir"); + return NULL; } - rewinddir(dfd); + rewinddir(dirp); - // 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 *)); + char * full_path = emalloc(PATH_MAX * sizeof(char)); struct stat stbuf; int i = 0; - while ((dp = readdir(dfd)) != NULL) { + while ((dp = readdir(dirp)) != 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; + return NULL; } - memset(full_path, 0, PATH_MAX * sizeof(char *)); + 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) { + if (stat(full_path, &stbuf) == -1) { perror("stat"); - return false; + return NULL; } - if ((stbuf.st_mode & S_IFMT ) == S_IFDIR) { + 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); @@ -90,17 +79,23 @@ struct pci_devices * get_pci_paths(void) { i++; } } + if (errno != 0) { + perror("readdir"); + return NULL; + } return pci; } +// For each PCI device in the list pci, fetch its vendor and +// device id using sysfs (e.g., /sys/bus/pci/devices/XXX/{vendor/device}) 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; + int path_size = strlen(PCI_PATH) + strlen(dev->path) + 2; // Read vendor_id char *vendor_id_path = emalloc(sizeof(char) * (path_size + strlen("vendor"))); @@ -116,7 +111,8 @@ void populate_pci_devices(struct pci_devices * pci) { // 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"); + 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; @@ -124,18 +120,28 @@ void populate_pci_devices(struct pci_devices * pci) { else { dev->device_id = strtol(buf, NULL, 16); } + + free(vendor_id_path); + free(device_id_path); } } -// 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. +// Right now, we are interested in PCI devices which +// vendor is NVIDIA (to be extended in the future). +// Should we also restrict to VGA controllers only? +bool pci_device_is_useful(struct pci_device* dev) { + return dev->vendor_id == PCI_VENDOR_NVIDIA; +} + +// Filter the input list in order to get only those PCI devices which +// we are interested in (decided by pci_device_is_useful) +// 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) { + if (pci_device_is_useful(pci->devices[i])) { devices_to_get[dev_ptr] = i; dev_ptr++; } @@ -143,27 +149,30 @@ struct pci_devices * filter_pci_devices(struct pci_devices * pci) { struct pci_devices * pci_filtered = emalloc(sizeof(struct pci_devices)); pci_filtered->num_devices = dev_ptr; - if (pci_filtered->num_devices == 0) + + if (pci_filtered->num_devices == 0) { pci_filtered->devices = NULL; - else + } + 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]]; + for (int i=0; i < pci_filtered->num_devices; i++) + pci_filtered->devices[i] = pci->devices[devices_to_get[i]]; } return pci_filtered; } +// Return a list of PCI devices that could be used to infer the SoC. +// The criteria to determine which devices are suitable for this task +// is decided in filter_pci_devices. struct pci_devices * get_pci_devices(void) { struct pci_devices * pci = get_pci_paths(); if (pci == NULL) - return false; + return NULL; - populate_pci_devices(pci); + populate_pci_devices(pci); - struct pci_devices * filtered = filter_pci_devices(pci); - - return filtered; + return filter_pci_devices(pci); } \ No newline at end of file