#include <inttypes.h>
#include <sys/io.h>
-#define MAX_PCI_FUNC 8
-#define MAX_PCI_DEVICES 32
-#define MAX_PCI_BUSES 256
+#define MAX_PCI_FUNC 8
+#define MAX_PCI_DEVICES 32
+#define MAX_PCI_BUSES 256
+#define LINUX_KERNEL_MODULE_SIZE 64
+#define PCI_VENDOR_NAME_SIZE 256
+#define PCI_PRODUCT_NAME_SIZE 256
+#define PCI_CLASS_NAME_SIZE 256
+#define MAX_KERNEL_MODULES_PER_PCI_DEVICE 10
typedef uint32_t pciaddr_t;
/* a structure for extended pci information */
/* XXX: use pointers for these? */
struct pci_dev_info {
- char vendor_name[256];
- char product_name[256];
- char linux_kernel_module[64];
- char class_name[256];
+ char vendor_name[PCI_VENDOR_NAME_SIZE];
+ char product_name[PCI_PRODUCT_NAME_SIZE];
+ char linux_kernel_module[LINUX_KERNEL_MODULE_SIZE][MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+ int linux_kernel_module_count;
+ char class_name[PCI_CLASS_NAME_SIZE];
};
/* PCI device (really, function) */
if (!dev->dev_info)
return -1;
}
- strcpy(dev->dev_info->linux_kernel_module, "unknown");
+ for (int i=0;i<MAX_KERNEL_MODULES_PER_PCI_DEVICE;i++) {
+ strlcpy(dev->dev_info->linux_kernel_module[i], "unknown",7);
+ }
}
/* Opening the modules.pcimap (of a linux kernel) from the boot device */
strcpy(product_id,"0000");
strcpy(sub_product_id,"0000");
strcpy(sub_vendor_id,"0000");
+ dev->dev_info->linux_kernel_module_count=0;
/* for each line we found in the modules.pcimap */
while ( fgets(line, sizeof line, f) ) {
(int_sub_product_id & dev->sub_product)
== dev->sub_product &&
(int_sub_vendor_id & dev->sub_vendor)
- == dev->sub_vendor)
- strcpy(dev->dev_info->linux_kernel_module, module_name);
+ == dev->sub_vendor) {
+ strcpy(dev->dev_info->linux_kernel_module[dev->dev_info->linux_kernel_module_count], module_name);
+ dev->dev_info->linux_kernel_module_count++;
+ }
}
}
fclose(f);
int get_class_name_from_pci_ids(struct pci_domain *domain)
{
char line[MAX_LINE];
- char class_name[255];
- char sub_class_name[255];
+ char class_name[PCI_CLASS_NAME_SIZE];
+ char sub_class_name[PCI_CLASS_NAME_SIZE];
char class_id_str[5];
char sub_class_id_str[5];
FILE *f;
if (!dev->dev_info)
return -1;
}
- strcpy(dev->dev_info->class_name,"unknown");
+ strlcpy(dev->dev_info->class_name,"unknown",7);
}
/* Opening the pci.ids from the boot device */
class_mode=true;
if (class_mode == false)
continue;
- strncpy(class_name,"unknown",7);
+ strlcpy(class_name,"unknown",7);
/* If the line doesn't start with a tab, it means that's a class name */
if (line[0] != '\t') {
class_id_str[2]=0;
/* the class name is the next field */
- strlcpy(class_name,skipspace(strstr(line," ")),255);
+ strlcpy(class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1);
remove_eol(class_name);
int int_class_id_str=hex_to_int(class_id_str);
/* assign the class_name to any matching pci device */
for_each_pci_func(dev, domain) {
if (int_class_id_str == dev->class[2])
- strlcpy(dev->dev_info->class_name,class_name,255);
+ strlcpy(dev->dev_info->class_name,class_name,PCI_CLASS_NAME_SIZE-1);
}
/* if we have a tab + a char, it means this is a sub class name */
} else if ((line[0] == '\t') && (line[1] != '\t')) {
/* the sub class name the second field */
- strlcpy(sub_class_name,skipspace(strstr(line," ")),255);
+ strlcpy(sub_class_name,skipspace(strstr(line," ")),PCI_CLASS_NAME_SIZE-1);
remove_eol(sub_class_name);
/* the sub class id is first field */
for_each_pci_func(dev, domain) {
if (int_class_id_str == dev->class[2] &&
int_sub_class_id_str == dev->class[1])
- strlcpy(dev->dev_info->class_name,sub_class_name,255);
+ strlcpy(dev->dev_info->class_name,sub_class_name,PCI_CLASS_NAME_SIZE-1);
}
}
int get_name_from_pci_ids(struct pci_domain *domain)
{
char line[MAX_LINE];
- char vendor[255];
+ char vendor[PCI_VENDOR_NAME_SIZE];
char vendor_id[5];
- char product[255];
+ char product[PCI_PRODUCT_NAME_SIZE];
char product_id[5];
char sub_product_id[5];
char sub_vendor_id[5];
/* the vendor name is the next field */
vendor_id[4]=0;
- strlcpy(vendor,skipspace(strstr(line," ")),255);
+ strlcpy(vendor,skipspace(strstr(line," ")),PCI_VENDOR_NAME_SIZE-1);
remove_eol(vendor);
/* init product_id, sub_product and sub_vendor */
} else if ((line[0] == '\t') && (line[1] != '\t') && (skip_to_next_vendor == false)) {
/* the product name the second field */
- strlcpy(product,skipspace(strstr(line," ")),255);
+ strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1);
remove_eol(product);
/* the product id is first field */
for_each_pci_func(dev, domain) {
if (int_vendor_id == dev->vendor &&
int_product_id == dev->product) {
- strlcpy(dev->dev_info->vendor_name,vendor,255);
- strlcpy(dev->dev_info->product_name,product,255);
+ strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1);
+ strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1);
}
}
} else if ((line[0] == '\t') && (line[1] == '\t') && (skip_to_next_vendor == false)) {
/* the product name is last field */
- strlcpy(product,skipspace(strstr(line," ")),255);
- strlcpy(product,skipspace(strstr(product," ")),255);
+ strlcpy(product,skipspace(strstr(line," ")),PCI_PRODUCT_NAME_SIZE-1);
+ strlcpy(product,skipspace(strstr(product," ")),PCI_PRODUCT_NAME_SIZE-1);
remove_eol(product);
/* the sub_vendor id is first field */
int_product_id == dev->product &&
int_sub_product_id == dev->sub_product &&
int_sub_vendor_id == dev->sub_vendor) {
- strlcpy(dev->dev_info->vendor_name,vendor,255);
- strlcpy(dev->dev_info->product_name,product,255);
+ strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1);
+ strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1);
}
}
}
# define dprintf(...) ((void)0)
#endif
-char display_line;
+char display_line=0;
#define moreprintf(...) \
do { \
display_line++; \
void display_pci_devices(struct pci_domain *pci_domain) {
struct pci_device *pci_device;
- int ndev = 0;
+ char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+
for_each_pci_func(pci_device, pci_domain) {
- printf("[%02x:%02x.%01x]: %s: %04x:%04x[%04x:%04x]) %s:%s\n",
- __pci_bus, __pci_slot, __pci_func,
- pci_device->dev_info->linux_kernel_module,
- pci_device->vendor, pci_device->product,
- pci_device->sub_vendor, pci_device->sub_product,
- pci_device->dev_info->vendor_name,
- pci_device->dev_info->product_name);
- ndev++;
+
+ memset(kernel_modules,0,sizeof kernel_modules);
+
+/* printf("PCI: found %d kernel modules for %04x:%04x[%04x:%04x]\n",
+ pci_device->dev_info->linux_kernel_module_count,
+ pci_device->vendor, pci_device->product,
+ pci_device->sub_vendor, pci_device->sub_product);
+*/
+ for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) {
+ if (i>0) {
+ strncat(kernel_modules," | ",3);
+ }
+ strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1);
+ }
+
+ moreprintf("%04x:%04x[%04x:%04x]: %s\n",
+ pci_device->vendor, pci_device->product,
+ pci_device->sub_vendor, pci_device->sub_product,
+ pci_device->dev_info->class_name);
+
+ moreprintf(" Vendor Name : %s\n", pci_device->dev_info->vendor_name);
+ moreprintf(" Product Name : %s\n", pci_device->dev_info->product_name);
+ moreprintf(" PCI bus position : %02x:%02x.%01x\n", __pci_bus, __pci_slot, __pci_func);
+ moreprintf(" Kernel modules : %s\n\n",kernel_modules);
}
- printf("PCI: %d devices found\n", ndev);
}
int main(int argc, char *argv[])
{
struct pci_domain *pci_domain;
+ int return_code=0;
+ int nb_pci_devices=0;
- openconsole(&dev_null_r, &dev_stdcon_w);
+ openconsole(&dev_stdcon_r, &dev_stdcon_w);
/* Scanning to detect pci buses and devices */
+ printf("PCI: Scanning PCI BUS\n");
pci_domain = pci_scan();
+ struct pci_device *pci_device;
+ for_each_pci_func(pci_device, pci_domain) {
+ nb_pci_devices++;
+ }
+
+ printf("PCI: %d PCI devices found\n",nb_pci_devices);
+
+
+ printf("PCI: Looking for device name\n");
/* Assigning product & vendor name for each device*/
- get_name_from_pci_ids(pci_domain);
+ return_code=get_name_from_pci_ids(pci_domain);
+ if (return_code == -ENOPCIIDS) {
+ printf("PCI: ERROR !\n");
+ printf("PCI: Unable to open pci.ids in the same directory as pcitest.c32.\n");
+ printf("PCI: PCI Device names can't be computed.\n");
+ }
+
+ printf("PCI: Resolving class names\n");
+ /* Assigning class name for each device*/
+ return_code=get_class_name_from_pci_ids(pci_domain);
+ if (return_code == -ENOPCIIDS) {
+ printf("PCI: ERROR !\n");
+ printf("PCI: Unable to open pci.ids in the same directory as pcitest.c32.\n");
+ printf("PCI: PCI class names can't be computed.\n");
+ }
+ printf("PCI: Looking for Kernel modules\n");
/* Detecting which kernel module should match each device */
- get_module_name_from_pci_ids(pci_domain);
+ return_code=get_module_name_from_pci_ids(pci_domain);
+ if (return_code == -ENOMODULESPCIMAP) {
+ printf("PCI: ERROR !\n");
+ printf("PCI: Unable to open modules.pcimap in the same directory as pcitest.c32.\n");
+ printf("PCI: Kernel Module names can't be computed.\n");
+ }
/* display the pci devices we found */
display_pci_devices(pci_domain);
void compute_pci_device(unsigned char *menu,struct pci_device *pci_device,int pci_bus, int pci_slot, int pci_func) {
char buffer[56];
char statbuffer[STATLEN];
+ char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE];
*menu = add_menu(" Details ",-1);
menu_count++;
snprintf(statbuffer,sizeof statbuffer,"vendor:product[sub_vendor:sub_product] : %04x:%04x[%04x:%04x]",pci_device->vendor, pci_device->product,pci_device->sub_vendor, pci_device->sub_product);
add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
- snprintf(buffer,sizeof buffer,"Module : %s",pci_device->dev_info->linux_kernel_module);
- snprintf(statbuffer,sizeof statbuffer,"Kernel Module: %s",pci_device->dev_info->linux_kernel_module);
+ if (pci_device->dev_info->linux_kernel_module_count>1) {
+ for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) {
+ if (i>0) {
+ strncat(kernel_modules," | ",3);
+ }
+ strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1);
+ }
+ snprintf(buffer,sizeof buffer,"Modules : %s",kernel_modules);
+ snprintf(statbuffer,sizeof statbuffer,"Kernel Modules: %s",kernel_modules);
+ } else {
+ snprintf(buffer,sizeof buffer,"Module : %s",pci_device->dev_info->linux_kernel_module[0]);
+ snprintf(statbuffer,sizeof statbuffer,"Kernel Module: %s",pci_device->dev_info->linux_kernel_module[0]);
+ }
add_item(buffer,statbuffer,OPT_INACTIVE,NULL,0);
}
char menuname[255][MENULEN+1];
char infobar[255][STATLEN+1];
struct pci_device *pci_device;
+ char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE];
+
printf("MENU: Computing PCI menu\n");
/* For every detected pci device, compute its submenu */
for_each_pci_func(pci_device, *pci_domain) {
+ memset(kernel_modules,0,sizeof kernel_modules);
+ for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) {
+ if (i>0) {
+ strncat(kernel_modules," | ",3);
+ }
+ strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1);
+ }
+ if (pci_device->dev_info->linux_kernel_module_count==0) strlcpy(kernel_modules,"unknown",7);
+
compute_pci_device(&PCI_SUBMENU[i],pci_device,__pci_bus,__pci_slot,__pci_func);
snprintf(menuname[i],59,"%s|%s",pci_device->dev_info->vendor_name,pci_device->dev_info->product_name);
snprintf(infobar[i], STATLEN,"%02x:%02x.%01x # %s # ID:%04x:%04x[%04x:%04x] # Kmod:%s\n",
__pci_bus, __pci_slot, __pci_func,pci_device->dev_info->class_name,
pci_device->vendor, pci_device->product,
- pci_device->sub_vendor, pci_device->sub_product,pci_device->dev_info->linux_kernel_module);
+ pci_device->sub_vendor, pci_device->sub_product,kernel_modules);
i++;
}
void compute_KERNEL(unsigned char *menu,struct pci_domain **pci_domain) {
char buffer[SUBMENULEN+1];
char infobar[STATLEN+1];
+ char kernel_modules [LINUX_KERNEL_MODULE_SIZE*MAX_KERNEL_MODULES_PER_PCI_DEVICE];
*menu = add_menu(" Kernel Modules ",-1);
menu_count++;
} else {
/* For every detected pci device, grab its kernel module to compute this submenu */
for_each_pci_func(pci_device, *pci_domain) {
+ memset(kernel_modules,0,sizeof kernel_modules);
+ for (int i=0; i<pci_device->dev_info->linux_kernel_module_count;i++) {
+ if (i>0) {
+ strncat(kernel_modules," | ",3);
+ }
+ strncat(kernel_modules, pci_device->dev_info->linux_kernel_module[i],LINUX_KERNEL_MODULE_SIZE-1);
+ }
+
/* No need to add unknown kernel modules*/
- if (strcmp("unknown",pci_device->dev_info->linux_kernel_module)!=0) {
- snprintf(buffer,sizeof buffer,"%s (%s)",pci_device->dev_info->linux_kernel_module, pci_device->dev_info->class_name);
+ if (strlen(kernel_modules)>0) {
+ snprintf(buffer,sizeof buffer,"%s (%s)",kernel_modules, pci_device->dev_info->class_name);
snprintf(infobar, sizeof infobar,"%04x:%04x %s : %s\n",
pci_device->vendor, pci_device->product,
pci_device->dev_info->vendor_name,