aboutsummaryrefslogtreecommitdiffstats
path: root/com32/lib
diff options
context:
space:
mode:
Diffstat (limited to 'com32/lib')
-rw-r--r--com32/lib/MCONFIG1
-rw-r--r--com32/lib/Makefile14
-rw-r--r--com32/lib/pci/scan.c219
-rw-r--r--com32/lib/strpcpy.c20
-rw-r--r--com32/lib/syslinux/pxe_get_nic.c61
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(&regs, 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, &regs, &regs);
+
+ memcpy(gnt, __com32.cs_bounce, sizeof(t_PXENV_UNDI_GET_NIC_TYPE));
+
+ if (regs.eflags.l & EFLAGS_CF)
+ return -1;
+
+ return gnt->Status;
+}