diff options
Diffstat (limited to 'com32/lib')
-rw-r--r-- | com32/lib/MCONFIG | 1 | ||||
-rw-r--r-- | com32/lib/Makefile | 14 | ||||
-rw-r--r-- | com32/lib/pci/scan.c | 219 | ||||
-rw-r--r-- | com32/lib/strpcpy.c | 20 | ||||
-rw-r--r-- | com32/lib/syslinux/pxe_get_nic.c | 61 |
5 files changed, 263 insertions, 52 deletions
diff --git a/com32/lib/MCONFIG b/com32/lib/MCONFIG index e40cf83c..aea0ed74 100644 --- a/com32/lib/MCONFIG +++ b/com32/lib/MCONFIG @@ -1,6 +1,5 @@ # -*- makefile -*- -topdir = ../.. include $(topdir)/MCONFIG GCCOPT := $(call gcc_ok,-std=gnu99,) \ diff --git a/com32/lib/Makefile b/com32/lib/Makefile index 0cc40617..6c137f9d 100644 --- a/com32/lib/Makefile +++ b/com32/lib/Makefile @@ -1,4 +1,10 @@ +# +# ONLY INCLUDE MIT OR 2/3-BSD-LICENSED CODE IN THIS LIBRARY +# + # Include configuration rules +NOGPL := 1 +topdir = ../.. include MCONFIG LIBOBJS = \ @@ -11,8 +17,8 @@ LIBOBJS = \ exit.o onexit.o \ perror.o printf.o puts.o qsort.o realloc.o seed48.o snprintf.o \ sprintf.o srand48.o sscanf.o stack.o strcasecmp.o strcat.o \ - strchr.o strcmp.o strcpy.o strdup.o strerror.o strlen.o \ - strnlen.o \ + strchr.o strcmp.o strcpy.o strpcpy.o strdup.o strlen.o \ + strerror.o strnlen.o \ strncasecmp.o strncat.o strncmp.o strncpy.o strndup.o \ stpcpy.o stpncpy.o \ strntoimax.o strntoumax.o strrchr.o strsep.o strspn.o strstr.o \ @@ -92,7 +98,7 @@ LIBOBJS = \ syslinux/initramfs_file.o syslinux/initramfs_loadfile.o \ syslinux/initramfs_archive.o \ \ - syslinux/pxe_get_cached.o \ + syslinux/pxe_get_cached.o syslinux/pxe_get_nic.o \ \ syslinux/adv.o syslinux/advwrite.o syslinux/getadv.o \ syslinux/setadv.o @@ -113,7 +119,7 @@ libcom32.a : $(LIBOBJS) tidy dist clean: rm -f sys/vesa/alphatbl.c - find . \( -name \*.o -o -name .\*.d -o -name \*.tmp \) -print0 | \ + find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \ xargs -0r rm -f spotless: clean diff --git a/com32/lib/pci/scan.c b/com32/lib/pci/scan.c index 98df0dd3..cfd9e654 100644 --- a/com32/lib/pci/scan.c +++ b/com32/lib/pci/scan.c @@ -73,7 +73,7 @@ static int hex_to_int(char *hexa) /* Try to match any pci device to the appropriate kernel module */ /* it uses the modules.pcimap from the boot device */ -int get_module_name_from_pci_ids(struct pci_domain *domain) +int get_module_name_from_pci_ids(struct pci_domain *domain, char *modules_pcimap_path) { char line[MAX_LINE]; char module_name[21]; // the module name field is 21 char long @@ -94,18 +94,21 @@ int get_module_name_from_pci_ids(struct pci_domain *domain) 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 */ - f=fopen("modules.pcimap", "r"); + f=fopen(modules_pcimap_path, "r"); if (!f) - return -1; + return -ENOMODULESPCIMAP; strcpy(vendor_id,"0000"); 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) ) { @@ -134,35 +137,136 @@ int get_module_name_from_pci_ids(struct pci_domain *domain) /* Searching the next field */ result = strtok( NULL, delims ); } + int int_vendor_id=hex_to_int(vendor_id); + int int_sub_vendor_id=hex_to_int(sub_vendor_id); + int int_product_id=hex_to_int(product_id); + int int_sub_product_id=hex_to_int(sub_product_id); /* if a pci_device matches an entry, fill the linux_kernel_module with the appropriate kernel module */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product && - (hex_to_int(sub_product_id) & dev->sub_product) + if (int_vendor_id == dev->vendor && + int_product_id == dev->product && + (int_sub_product_id & dev->sub_product) == dev->sub_product && - (hex_to_int(sub_vendor_id) & dev->sub_vendor) - == dev->sub_vendor) - strcpy(dev->dev_info->linux_kernel_module, module_name); + (int_sub_vendor_id & dev->sub_vendor) + == 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); + return 0; +} + +/* Try to match any pci device to the appropriate class name */ +/* it uses the pci.ids from the boot device */ +int get_class_name_from_pci_ids(struct pci_domain *domain, char *pciids_path) +{ + char line[MAX_LINE]; + 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; + struct pci_device *dev; + bool class_mode=false; + + /* Intializing the vendor/product name for each pci device to "unknown" */ + /* adding a dev_info member if needed */ + for_each_pci_func(dev, domain) { + /* initialize the dev_info structure if it doesn't exist yet. */ + if (! dev->dev_info) { + dev->dev_info = zalloc(sizeof *dev->dev_info); + if (!dev->dev_info) + return -1; + } + strlcpy(dev->dev_info->class_name,"unknown",7); + } + + /* Opening the pci.ids from the boot device */ + f = fopen(pciids_path,"r"); + if (!f) + return -ENOPCIIDS; + + /* for each line we found in the pci.ids */ + while ( fgets(line, sizeof line, f) ) { + /* Skipping uncessary lines */ + if ((line[0] == '#') || (line[0] == ' ') || + (line[0] == 10)) + continue; + + /* Until we found a line starting with a 'C', we are not parsing classes */ + if (line[0] == 'C') + class_mode=true; + if (class_mode == false) + continue; + 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') { + + /* ignore the two first char and then copy 2 chars (class id)*/ + strlcpy(class_id_str,&line[2],2); + class_id_str[2]=0; + + /* the class name is the next field */ + 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,PCI_CLASS_NAME_SIZE-1); + /* This value is usually the main category*/ + strlcpy(dev->dev_info->category_name,class_name+4,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," ")),PCI_CLASS_NAME_SIZE-1); + remove_eol(sub_class_name); + + /* the sub class id is first field */ + strlcpy(sub_class_id_str,&line[1],2); + sub_class_id_str[2]=0; + + int int_class_id_str=hex_to_int(class_id_str); + int int_sub_class_id_str=hex_to_int(sub_class_id_str); + /* assign the product_name to any matching pci device */ + 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,PCI_CLASS_NAME_SIZE-1); + } + } } fclose(f); return 0; } + /* Try to match any pci device to the appropriate vendor and product name */ /* it uses the pci.ids from the boot device */ -int get_name_from_pci_ids(struct pci_domain *domain) +int get_name_from_pci_ids(struct pci_domain *domain, char *pciids_path) { 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]; FILE *f; struct pci_device *dev; + bool skip_to_next_vendor=false; + uint16_t int_vendor_id; + uint16_t int_product_id; + uint16_t int_sub_product_id; + uint16_t int_sub_vendor_id; /* Intializing the vendor/product name for each pci device to "unknown" */ /* adding a dev_info member if needed */ @@ -173,19 +277,19 @@ int get_name_from_pci_ids(struct pci_domain *domain) if (!dev->dev_info) return -1; } - strcpy(dev->dev_info->vendor_name,"unknown"); - strcpy(dev->dev_info->product_name,"unknown"); + strlcpy(dev->dev_info->vendor_name,"unknown",7); + strlcpy(dev->dev_info->product_name,"unknown",7); } /* Opening the pci.ids from the boot device */ - f = fopen("pci.ids","r"); + f = fopen(pciids_path,"r"); if (!f) - return -1; + return -ENOPCIIDS; - strcpy(vendor_id,"0000"); - strcpy(product_id,"0000"); - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(vendor_id,"0000",4); + strlcpy(product_id,"0000",4); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); /* for each line we found in the pci.ids */ while ( fgets(line, sizeof line, f) ) { @@ -193,6 +297,7 @@ int get_name_from_pci_ids(struct pci_domain *domain) if ((line[0] == '#') || (line[0] == ' ') || (line[0] == 'C') || (line[0] == 10)) continue; + /* If the line doesn't start with a tab, it means that's a vendor id */ if (line[0] != '\t') { @@ -201,26 +306,35 @@ int get_name_from_pci_ids(struct pci_domain *domain) /* 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 */ - strcpy(product_id,"0000"); - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(product_id,"0000",4); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); - /* ffff is an invalid vendor id */ - if (strstr(vendor_id,"ffff")) break; - /* assign the vendor_name to any matching pci device */ + /* Unless we found a matching device, we have to skip to the next vendor */ + skip_to_next_vendor=true; + + int_vendor_id=hex_to_int(vendor_id); + /* Iterate in all pci devices to find a matching vendor */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor) - strlcpy(dev->dev_info->vendor_name,vendor,255); + /* if one device that match this vendor */ + if (int_vendor_id == dev->vendor) { + /* copy the vendor name for this device */ + strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1); + /* Some pci devices match this vendor, so we have to found them */ + skip_to_next_vendor=false; + /* Let's loop on the other devices as some may have the same vendor */ + } } - /* if we have a tab + a char, it means this is a product id */ - } else if ((line[0] == '\t') && (line[1] != '\t')) { + /* if we have a tab + a char, it means this is a product id + * but we only look at it if we own some pci devices of the current 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 */ @@ -228,22 +342,27 @@ int get_name_from_pci_ids(struct pci_domain *domain) product_id[4]=0; /* init sub_product and sub_vendor */ - strcpy(sub_product_id,"0000"); - strcpy(sub_vendor_id,"0000"); + strlcpy(sub_product_id,"0000",4); + strlcpy(sub_vendor_id,"0000",4); + int_vendor_id=hex_to_int(vendor_id); + int_product_id=hex_to_int(product_id); /* assign the product_name to any matching pci device */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product) - strlcpy(dev->dev_info->product_name,product,255); + if (int_vendor_id == dev->vendor && + int_product_id == dev->product) { + strlcpy(dev->dev_info->vendor_name,vendor,PCI_VENDOR_NAME_SIZE-1); + strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1); + } } - /* if we have two tabs, it means this is a sub product */ - } else if ((line[0] == '\t') && (line[1] == '\t')) { + /* if we have two tabs, it means this is a sub product + * but we only look at it if we own some pci devices of the current vendor*/ + } 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 */ @@ -254,13 +373,19 @@ int get_name_from_pci_ids(struct pci_domain *domain) strlcpy(sub_product_id,&line[7],4); sub_product_id[4]=0; + int_vendor_id=hex_to_int(vendor_id); + int_sub_vendor_id=hex_to_int(sub_vendor_id); + int_product_id=hex_to_int(product_id); + int_sub_product_id=hex_to_int(sub_product_id); /* assign the product_name to any matching pci device */ for_each_pci_func(dev, domain) { - if (hex_to_int(vendor_id) == dev->vendor && - hex_to_int(product_id) == dev->product && - hex_to_int(sub_product_id) == dev->sub_product && - hex_to_int(sub_vendor_id) == dev->sub_vendor) - strlcpy(dev->dev_info->product_name,product,255); + if (int_vendor_id == dev->vendor && + 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,PCI_VENDOR_NAME_SIZE-1); + strlcpy(dev->dev_info->product_name,product,PCI_PRODUCT_NAME_SIZE-1); + } } } } diff --git a/com32/lib/strpcpy.c b/com32/lib/strpcpy.c new file mode 100644 index 00000000..e181e78f --- /dev/null +++ b/com32/lib/strpcpy.c @@ -0,0 +1,20 @@ +/* + * strpcpy.c + * + * strpcpy() - strcpy() which returns a pointer to the final null + */ + +#include <string.h> + +char *strpcpy(char *dst, const char *src) +{ + char *q = dst; + const char *p = src; + char ch; + + do { + *q++ = ch = *p++; + } while ( ch ); + + return q-1; +} diff --git a/com32/lib/syslinux/pxe_get_nic.c b/com32/lib/syslinux/pxe_get_nic.c new file mode 100644 index 00000000..b779542c --- /dev/null +++ b/com32/lib/syslinux/pxe_get_nic.c @@ -0,0 +1,61 @@ +/* ----------------------------------------------------------------------- * + * + * Copyright 2007-2008 H. Peter Anvin - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom + * the Software is furnished to do so, subject to the following + * conditions: + * + * The above copyright notice and this permission notice shall + * be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * ----------------------------------------------------------------------- */ + +/* + * pxe_get_cached.c + * + * PXE call "get cached info" + */ + +#include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <com32.h> + +#include <syslinux/pxe.h> + +/* Returns the status code from PXE (0 on success), + or -1 on invocation failure */ +int pxe_get_nic_type(t_PXENV_UNDI_GET_NIC_TYPE *gnt) +{ + com32sys_t regs; + + memset(®s, 0, sizeof regs); + regs.eax.w[0] = 0x0009; + regs.ebx.w[0] = PXENV_UNDI_GET_NIC_TYPE; + regs.es = SEG( __com32.cs_bounce); + regs.edi.w[0] = OFFS( __com32.cs_bounce); + + __intcall(0x22, ®s, ®s); + + memcpy(gnt, __com32.cs_bounce, sizeof(t_PXENV_UNDI_GET_NIC_TYPE)); + + if (regs.eflags.l & EFLAGS_CF) + return -1; + + return gnt->Status; +} |