All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: linux-kernel@vger.kernel.org
Cc: Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de>,
	greg@kroah.com, jgarzik@pobox.com
Subject: [PATCH] Module alias and device table support.
Date: Fri, 31 Jan 2003 11:09:38 +1100	[thread overview]
Message-ID: <20030131002043.947632C056@lists.samba.org> (raw)

This patch adds MODULE_ALIAS("foo") capability, and uses it to
automatically generate sensible aliases from device tables.  The
post-processing is a little rough, but works.

Name: Module alias and device table support
Author: Rusty Russell
Status: Tested on 2.5.59

D: Introduces "MODULE_ALIAS" which modules can use to embed their own
D: aliases for modprobe to use.  Also adds a "finishing" step to modules to
D: supplement their aliases based on MODULE_TABLE declarations, eg.
D: 'usb:v0506p4601dl*dh*dc*dsc*dp*ic*isc*ip*' for drivers/usb/net/pegasus.o

diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/include/linux/isapnp.h working-2.5.59-alias/include/linux/isapnp.h
--- linux-2.5.59/include/linux/isapnp.h	2003-01-14 10:13:08.000000000 +1100
+++ working-2.5.59-alias/include/linux/isapnp.h	2003-01-30 16:13:12.000000000 +1100
@@ -69,8 +69,9 @@
 
 /* export used IDs outside module */
 #define ISAPNP_CARD_TABLE(name) \
-		MODULE_GENERIC_TABLE(isapnp_card, name)
+		MODULE_TABLE(isapnp_card, name)
 
+/* If you change this, you must update scripts/table2alias.c. */
 struct isapnp_card_id {
 	unsigned long driver_data;	/* data private to the driver */
 	unsigned short card_vendor, card_device;
@@ -85,6 +86,7 @@ struct isapnp_card_id {
 #define ISAPNP_DEVICE_SINGLE_END \
 		.card_vendor = 0, .card_device = 0
 
+/* If you change this, you must update scripts/table2alias.c. */
 struct isapnp_device_id {
 	unsigned short card_vendor, card_device;
 	unsigned short vendor, function;
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/include/linux/module.h working-2.5.59-alias/include/linux/module.h
--- linux-2.5.59/include/linux/module.h	2003-01-17 17:01:18.000000000 +1100
+++ working-2.5.59-alias/include/linux/module.h	2003-01-30 17:56:37.000000000 +1100
@@ -50,13 +50,14 @@ search_extable(const struct exception_ta
 	       unsigned long value);
 
 #ifdef MODULE
+#define ___module_cat(a,b) a ## b
+#define __module_cat(a,b) ___module_cat(a,b)
+/* For userspace: you can also call me... */
+#define MODULE_ALIAS(alias)					\
+	static const char __module_cat(__alias_,__LINE__)[]	\
+		__attribute__((section(".modalias"),unused)) = alias
 
-/* For replacement modutils, use an alias not a pointer. */
 #define MODULE_GENERIC_TABLE(gtype,name)			\
-static const unsigned long __module_##gtype##_size		\
-  __attribute__ ((unused)) = sizeof(struct gtype##_id);		\
-static const struct gtype##_id * __module_##gtype##_table	\
-  __attribute__ ((unused)) = name;				\
 extern const struct gtype##_id __mod_##gtype##_table		\
   __attribute__ ((unused, alias(__stringify(name))))
 
@@ -96,6 +97,7 @@ extern const struct gtype##_id __mod_##g
 
 #else  /* !MODULE */
 
+#define MODULE_ALIAS(alias)
 #define MODULE_GENERIC_TABLE(gtype,name)
 #define THIS_MODULE ((struct module *)0)
 #define MOD_INC_USE_COUNT	do { } while (0)
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/include/linux/pci.h working-2.5.59-alias/include/linux/pci.h
--- linux-2.5.59/include/linux/pci.h	2003-01-02 14:48:00.000000000 +1100
+++ working-2.5.59-alias/include/linux/pci.h	2003-01-30 16:13:12.000000000 +1100
@@ -491,6 +491,7 @@ struct pbus_set_ranges_data
 	unsigned long prefetch_start, prefetch_end;
 };
 
+/* If you change this, you must update scripts/table2alias.c. */
 struct pci_device_id {
 	unsigned int vendor, device;		/* Vendor and device ID or PCI_ANY_ID */
 	unsigned int subvendor, subdevice;	/* Subsystem ID's or PCI_ANY_ID */
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/include/linux/usb.h working-2.5.59-alias/include/linux/usb.h
--- linux-2.5.59/include/linux/usb.h	2003-01-17 17:01:18.000000000 +1100
+++ working-2.5.59-alias/include/linux/usb.h	2003-01-30 16:13:12.000000000 +1100
@@ -371,6 +371,7 @@ static inline int usb_make_path (struct 
  * matches towards the beginning of your table, so that driver_info can
  * record quirks of specific products.
  */
+/* If you change this, you must update scripts/table2alias.c. */
 struct usb_device_id {
 	/* which fields to match against? */
 	__u16		match_flags;
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/scripts/Makefile working-2.5.59-alias/scripts/Makefile
--- linux-2.5.59/scripts/Makefile	2003-01-02 12:45:31.000000000 +1100
+++ working-2.5.59-alias/scripts/Makefile	2003-01-30 16:13:12.000000000 +1100
@@ -8,7 +8,7 @@
 # docproc: 	 Preprocess .tmpl file in order to generate .sgml documentation
 # conmakehash:	 Create arrays for initializing the kernel console tables
 
-host-progs    := fixdep split-include conmakehash docproc kallsyms
+host-progs    := fixdep split-include conmakehash docproc kallsyms table2alias
 build-targets := $(host-progs)
 
 # Let clean descend into subdirs
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/scripts/Makefile.build working-2.5.59-alias/scripts/Makefile.build
--- linux-2.5.59/scripts/Makefile.build	2003-01-17 17:01:18.000000000 +1100
+++ working-2.5.59-alias/scripts/Makefile.build	2003-01-30 17:51:31.000000000 +1100
@@ -175,11 +175,16 @@ endif
 quiet_cmd_link_multi-y = LD      $@
 cmd_link_multi-y = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) -r -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.o=-objs))) $($(subst $(obj)/,,$(@:.o=-y)))),$^)
 
+ifdef CONFIG_HOTPLUG
+module_link_hotplug-multi = `$(CONFIG_SHELL) scripts/extract_aliases $@.aliases "$(modname_flags)" $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^)`
+module_link_hotplug-single = `$(CONFIG_SHELL) scripts/extract_aliases $@.aliases "$(modname_flags)" $<`
+endif
+
 quiet_cmd_link_multi-m = LD [M]  $@
-cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^) init/vermagic.o
+cmd_link_multi-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $(filter $(addprefix $(obj)/,$($(subst $(obj)/,,$(@:.ko=-objs))) $($(subst $(obj)/,,$(@:.ko=-y)))),$^) $(module_link_hotplug-multi) init/vermagic.o 
 
 quiet_cmd_link_single-m = LD [M]  $@
-cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o
+cmd_link_single-m = $(LD) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LDFLAGS_MODULE) -o $@ $< init/vermagic.o $(module_link_hotplug-single)
 
 # Don't rebuilt vermagic.o unless we actually are in the init/ dir
 ifneq ($(obj),init)
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/scripts/extract_aliases working-2.5.59-alias/scripts/extract_aliases
--- linux-2.5.59/scripts/extract_aliases	1970-01-01 10:00:00.000000000 +1000
+++ working-2.5.59-alias/scripts/extract_aliases	2003-01-30 18:06:59.000000000 +1100
@@ -0,0 +1,21 @@
+#! /bin/sh
+
+# Look for module tables, and if found, put them in the object file
+# and print its name.
+set -e
+
+OUTPUT="$1"
+MODNAME_FLAGS="$2"
+shift 2
+
+$NM --no-sort --print-size --radix=d --print-file-name "$@" | 
+    grep '__mod_[a-z_]*_table' | 
+    while IFS=": " read FILE OFFSET SIZE TYPE NAME; do
+	scripts/table2alias $NAME $FILE $OFFSET $SIZE
+    done > $OUTPUT.c
+
+if [ -s $OUTPUT.c ]; then
+    $CC $CFLAGS $NOSTDINC_FLAGS $EXTRA_CFLAGS $MODNAME_FLAGS -DMODULE -include include/linux/module.h -c -o $OUTPUT.o $OUTPUT.c
+    echo $OUTPUT.o
+fi
+rm $OUTPUT.c
diff -urNp --exclude TAGS -X /home/rusty/current-dontdiff --minimal linux-2.5.59/scripts/table2alias.c working-2.5.59-alias/scripts/table2alias.c
--- linux-2.5.59/scripts/table2alias.c	1970-01-01 10:00:00.000000000 +1000
+++ working-2.5.59-alias/scripts/table2alias.c	2003-01-30 17:49:45.000000000 +1100
@@ -0,0 +1,244 @@
+/* Simple code to turn various tables into module aliases.
+   This deals with kernel datastructures where they should be
+   dealt with: in the kernel source.
+   (C) 2002 Rusty Russell IBM Corporation.
+*/
+#include <stdint.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* We need __LITTLE_ENDIAN/__BIG_ENDIAN and BITS_PER_LONG */
+#define __KERNEL__
+#include "../include/asm/byteorder.h"
+#include "../include/asm/types.h"
+
+#if BITS_PER_LONG == 32
+typedef uint32_t kernel_long_t;
+#elif BITS_PER_LONG == 64
+typedef uint64_t kernel_long_t;
+#else
+#error Unknown BITS_PER_LONG
+#endif
+
+/* If we're cross-compiling, we could have any wierd endian
+   combination.  Keep it simple. */
+static kernel_long_t __to_native(unsigned char *ptr, unsigned int size)
+{
+        unsigned int i;
+        kernel_long_t ret = 0;
+
+#ifdef __LITTLE_ENDIAN
+        for (i = 0; i < size; i++)
+                ret += ((unsigned long long)ptr[size - 1 - i]) << (i * 8);
+#elif defined(__BIG_ENDIAN)
+        for (i = 0; i < size; i++)
+                ret += ((unsigned long long)ptr[i]) << (i * 8);
+#else
+#error Must be big or little endian.
+#endif
+	return ret;
+}
+
+#define TO_NATIVE(x) (x) = __to_native((void *)&(x), sizeof(x))
+
+#define USB_DEVICE_ID_MATCH_VENDOR              0x0001
+#define USB_DEVICE_ID_MATCH_PRODUCT             0x0002
+#define USB_DEVICE_ID_MATCH_DEV_LO              0x0004
+#define USB_DEVICE_ID_MATCH_DEV_HI              0x0008
+#define USB_DEVICE_ID_MATCH_DEV_CLASS           0x0010
+#define USB_DEVICE_ID_MATCH_DEV_SUBCLASS        0x0020
+#define USB_DEVICE_ID_MATCH_DEV_PROTOCOL        0x0040
+#define USB_DEVICE_ID_MATCH_INT_CLASS           0x0080
+#define USB_DEVICE_ID_MATCH_INT_SUBCLASS        0x0100
+#define USB_DEVICE_ID_MATCH_INT_PROTOCOL        0x0200
+
+struct usb_device_id {
+        /* which fields to match against? */
+        uint16_t        match_flags;
+
+        /* Used for product specific matches; range is inclusive */
+        uint16_t        idVendor;
+        uint16_t        idProduct;
+        uint16_t        bcdDevice_lo;
+        uint16_t        bcdDevice_hi;
+
+        /* Used for device class matches */
+        uint8_t         bDeviceClass;
+        uint8_t         bDeviceSubClass;
+        uint8_t         bDeviceProtocol;
+
+        /* Used for interface class matches */
+        uint8_t         bInterfaceClass;
+        uint8_t         bInterfaceSubClass;
+        uint8_t         bInterfaceProtocol;
+
+        /* not matched against */
+        kernel_long_t   driver_info;
+};
+
+#define ADD(str, sep, cond, field)                              \
+do {                                                            \
+        strcat(str, sep);                                       \
+        if (cond)                                               \
+                sprintf(str + strlen(str),                      \
+                        sizeof(field) == 1 ? "%02X" :           \
+                        sizeof(field) == 2 ? "%04X" :           \
+                        sizeof(field) == 4 ? "%08X" : "",       \
+                        field);                                 \
+        else                                                    \
+                sprintf(str + strlen(str), "*");                \
+} while(0)
+
+/* Looks like "usb:vNpNdlNdhNdcNdscNdpNicNiscNipN" */
+static void do_usb_table(struct usb_device_id *ids, unsigned int size,
+			 const char *filename)
+{
+	unsigned int i;
+        char alias[200];
+
+	/* Should be exact multiple. */
+	if (size % sizeof(ids[0]))
+		fprintf(stderr, "WARNING: %s USB ids size has %u left\n",
+			filename, size % sizeof(ids[0]));
+	for (i = 0; i < size / sizeof(ids[0]); i++) {
+                TO_NATIVE(ids[i].match_flags);
+                TO_NATIVE(ids[i].idVendor);
+                TO_NATIVE(ids[i].idProduct);
+                TO_NATIVE(ids[i].bcdDevice_lo);
+                TO_NATIVE(ids[i].bcdDevice_hi);
+
+                strcpy(alias, "usb:");
+                ADD(alias, "v", ids[i].match_flags&USB_DEVICE_ID_MATCH_VENDOR,
+                    ids[i].idVendor);
+                ADD(alias, "p", ids[i].match_flags&USB_DEVICE_ID_MATCH_PRODUCT,
+                    ids[i].idProduct);
+                ADD(alias, "dl", ids[i].match_flags&USB_DEVICE_ID_MATCH_DEV_LO,
+                    ids[i].bcdDevice_lo);
+                ADD(alias, "dh", ids[i].match_flags&USB_DEVICE_ID_MATCH_DEV_HI,
+                    ids[i].bcdDevice_hi);
+                ADD(alias, "dc", ids[i].match_flags&USB_DEVICE_ID_MATCH_DEV_CLASS,
+                    ids[i].bDeviceClass);
+                ADD(alias, "dsc",
+		    ids[i].match_flags&USB_DEVICE_ID_MATCH_DEV_SUBCLASS,
+                    ids[i].bDeviceSubClass);
+                ADD(alias, "dp",
+		    ids[i].match_flags&USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+                    ids[i].bDeviceProtocol);
+                ADD(alias, "ic",
+		    ids[i].match_flags&USB_DEVICE_ID_MATCH_INT_CLASS,
+                    ids[i].bInterfaceClass);
+                ADD(alias, "isc",
+		    ids[i].match_flags&USB_DEVICE_ID_MATCH_INT_SUBCLASS,
+                    ids[i].bInterfaceSubClass);
+                ADD(alias, "ip",
+		    ids[i].match_flags&USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+                    ids[i].bInterfaceProtocol);
+		/* Always end in a wildcard, for future extension */
+		if (alias[strlen(alias)-1] != '*')
+			strcat(alias, "*");
+                printf("MODULE_ALIAS(\"%s\");\n", alias);
+        }
+}
+
+#define PCI_ANY_ID (~0)
+
+struct pci_device_id {
+        unsigned int vendor, device;   /* Vendor and device ID or PCI_ANY_ID */
+        unsigned int subvendor, subdevice; /* Subsystem ID's or PCI_ANY_ID */
+        unsigned int class, class_mask; /* (class,subclass,prog-if) triplet */
+        kernel_long_t driver_data;        /* Data private to the driver */
+};
+
+/* Looks like: pci:vNdNsvNsdNcN. */
+static void do_pci_table(struct pci_device_id *ids, unsigned int size,
+			 const char *filename)
+{
+	unsigned int i;
+        char alias[200];
+
+	/* Should be exact multiple. */
+	if (size % sizeof(ids[0]))
+		fprintf(stderr, "WARNING: %s PCI ids size has %u left\n",
+			filename, size % sizeof(ids[0]));
+	for (i = 0; i < size / sizeof(ids[0]); i++) {
+                TO_NATIVE(ids[i].vendor);
+                TO_NATIVE(ids[i].device);
+                TO_NATIVE(ids[i].subvendor);
+                TO_NATIVE(ids[i].subdevice);
+                TO_NATIVE(ids[i].class);
+                TO_NATIVE(ids[i].class_mask);
+
+                strcpy(alias, "pci:");
+                ADD(alias, "v", ids[i].vendor != PCI_ANY_ID, ids[i].vendor);
+                ADD(alias, "d", ids[i].device != PCI_ANY_ID, ids[i].device);
+                ADD(alias, "sv", ids[i].subvendor != PCI_ANY_ID, ids[i].subvendor);
+                ADD(alias, "sd", ids[i].subdevice != PCI_ANY_ID, ids[i].subdevice);
+                if (ids[i].class_mask != 0 && ids[i].class_mask != ~0) {
+                        fprintf(stderr,
+				"Can't handle strange class_mask in %s:%04X\n",
+				filename, ids[i].class_mask);
+                        exit(1);
+                }
+                ADD(alias, "c", ids[i].class != PCI_ANY_ID, ids[i].subvendor);
+		/* Always end in a wildcard, for future extension */
+		if (alias[strlen(alias)-1] != '*')
+			strcat(alias, "*");
+                printf("MODULE_ALIAS(\"%s\");\n", alias);
+        }
+}
+
+int main(int argc, char *argv[])
+{
+	int ret, fd;
+	unsigned int size, offset;
+	void *file;
+
+        if (argc != 5) {
+                fprintf(stderr,
+                        "Usage: table2alias <type> <file> <offset> <size>\n"
+                        "  Where type is __mod_{pci, usb}_device_table.\n");
+                exit(1);
+        }
+
+	/* Suck it in. */
+	offset = atoi(argv[3]);
+	size = atoi(argv[4]);
+	file = malloc(size);
+
+	fd = open(argv[2], O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "opening %s: %s\n", argv[2], strerror(errno));
+		exit(1);
+	}
+	if (lseek(fd, offset, SEEK_SET) == (off_t)-1) {
+		fprintf(stderr, "seeking to %u in %s: %s\n",
+			offset, argv[2], strerror(errno));
+		exit(1);
+	}
+
+	offset = 0;
+	while (offset < size) {
+		ret = read(fd, file+offset, size-offset);
+		if (ret < 0) {
+			fprintf(stderr, "reading from %s: %s\n",
+				argv[2], strerror(errno));
+			exit(1);
+		}
+		offset += ret;
+	} 
+
+        if (strcmp(argv[1], "__mod_usb_device_table") == 0)
+                do_usb_table(file, size, argv[2]);
+        else if (strcmp(argv[1], "__mod_pci_device_table") == 0)
+                do_pci_table(file, size, argv[2]);
+        else {
+                fprintf(stderr, "table2alias: unknown type %s\n", argv[1]);
+                exit(1);
+        }
+        exit(0);
+}

--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

             reply	other threads:[~2003-01-31  0:11 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-31  0:09 Rusty Russell [this message]
2003-01-31  6:23 ` [PATCH] Module alias and device table support Kai Germaschewski
2003-01-31  9:41   ` Horst von Brand
2003-01-31 15:42     ` Ingo Oeser
2003-01-31 22:33   ` Roman Zippel
2003-02-01  0:48     ` Kai Germaschewski
2003-02-01  1:22       ` Roman Zippel
2003-02-01  2:59         ` Kai Germaschewski
2003-02-01 10:31           ` Roman Zippel
2003-02-01  3:49   ` Rusty Russell
2003-02-01  7:20     ` Kai Germaschewski
2003-02-01 23:02     ` Horst von Brand
2003-02-03  0:52       ` Rusty Russell
2003-02-03  2:49         ` John Levon
2003-02-03 10:34           ` Rusty Russell
2003-02-04  9:56             ` Horst von Brand
2003-02-05  0:00               ` Rusty Russell
2003-02-03  8:31         ` Horst von Brand
2003-02-03 10:52           ` Rusty Russell
2003-02-04  8:05             ` Horst von Brand
2003-02-04  8:51               ` Rusty Russell
2003-02-06 23:09                 ` [PATCH] Restore module support Roman Zippel
2003-02-06 23:25                   ` Greg KH
2003-02-07  0:01                     ` Roman Zippel
2003-02-07  4:06                       ` Greg KH
2003-02-07  9:39                         ` Roman Zippel
2003-02-07 18:01                         ` Roman Zippel
2003-02-07  0:10                     ` Russell King
2003-02-07  4:53                       ` Rusty Russell
2003-02-07 10:03                         ` Russell King
2003-02-07  6:12                       ` Kai Germaschewski
2003-02-07  9:46                         ` Roman Zippel
2003-02-04 14:49               ` [PATCH] Module alias and device table support Roman Zippel
2003-02-03 13:40           ` Roman Zippel
     [not found] <20030201073007$5418@gated-at.bofh.it>
     [not found] ` <20030201073007$3e7f@gated-at.bofh.it>
2003-02-01 10:36   ` Arnd Bergmann
  -- strict thread matches above, loose matches on Subject: below --
2003-02-04 17:25 Adam J. Richter
2003-02-04 17:45 Adam J. Richter
2003-02-05  0:17 ` Rusty Russell

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20030131002043.947632C056@lists.samba.org \
    --to=rusty@rustcorp.com.au \
    --cc=greg@kroah.com \
    --cc=jgarzik@pobox.com \
    --cc=kai@tp1.ruhr-uni-bochum.de \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.