lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:	Sun, 17 Jun 2007 22:27:27 +0200
From:	Thomas Renninger <trenn@...e.de>
To:	Len Brown <lenb@...nel.org>
Cc:	linux-kernel <linux-kernel@...r.kernel.org>,
	linux-acpi <linux-acpi@...r.kernel.org>,
	Kay Sievers <kasievers@...e.de>
Subject: [PATCH 2/3] ACPI autoloading - Create acpi alias interface

Create acpi alias interface

Modify modpost (file2alias.c) to add acpi*:XYZ0001: alias in modules.alias
like:
grep acpi /lib/modules/2.6.22-rc4-default/modules.alias 
alias acpi*:SNY5001:* sony_laptop
alias acpi*:SNY6001:* sony_laptop
for e.g. the sony_laptop module.
This module matches against all ACPI devices with a HID or CID of SNY5001
or SNY6001

Export an uevent and modalias sysfs file containing the string:
[MODALIAS=]acpi:PNP0C0C:
additional CIDs are concatenated at the end.

Signed-off-by: Thomas Renninger <trenn@...e.de>

---
 drivers/acpi/scan.c             |  185 +++++++++++++++++++++++++++++++---------
 drivers/pnp/pnpacpi/core.c      |   18 ++-
 include/linux/acpi.h            |    1 
 include/linux/mod_devicetable.h |   15 +++
 scripts/mod/file2alias.c        |   12 ++
 5 files changed, 183 insertions(+), 48 deletions(-)

Index: linux-2.6.22-rc4/include/linux/mod_devicetable.h
===================================================================
--- linux-2.6.22-rc4.orig/include/linux/mod_devicetable.h
+++ linux-2.6.22-rc4/include/linux/mod_devicetable.h
@@ -159,6 +159,21 @@ struct ap_device_id {
 
 #define AP_DEVICE_ID_MATCH_DEVICE_TYPE		0x01
 
+#define ACPI_ID_LEN	9
+
+/*
+  Similar exists in include/acpi/acmacros.h
+  use this one for acpi linux specific stuff e.g.
+  in ACPI modules and the other one inside the
+  interpreter
+*/
+
+/* Exists already in acpi includes (include/acpi/actypes.h) */
+
+struct acpi_device_id {
+	__u8 id[ACPI_ID_LEN];
+	kernel_ulong_t driver_data;
+};
 
 #define PNP_ID_LEN	8
 #define PNP_MAX_DEVICES	8
Index: linux-2.6.22-rc4/scripts/mod/file2alias.c
===================================================================
--- linux-2.6.22-rc4.orig/scripts/mod/file2alias.c
+++ linux-2.6.22-rc4/scripts/mod/file2alias.c
@@ -290,6 +290,14 @@ static int do_serio_entry(const char *fi
 	return 1;
 }
 
+/* looks like: "acpi:ACPI0003 or acpi:PNP0C0B" */
+static int do_acpi_entry(const char *filename,
+			struct acpi_device_id *id, char *alias)
+{
+	sprintf(alias, "acpi*:%s:", id->id);
+	return 1;
+}
+
 /* looks like: "pnp:dD" */
 static int do_pnp_entry(const char *filename,
 			struct pnp_device_id *id, char *alias)
@@ -551,6 +559,10 @@ void handle_moddevtable(struct module *m
 		do_table(symval, sym->st_size,
 			 sizeof(struct serio_device_id), "serio",
 			 do_serio_entry, mod);
+	else if (sym_is(symname, "__mod_acpi_device_table"))
+		do_table(symval, sym->st_size,
+			 sizeof(struct acpi_device_id), "acpi",
+			 do_acpi_entry, mod);
 	else if (sym_is(symname, "__mod_pnp_device_table"))
 		do_table(symval, sym->st_size,
 			 sizeof(struct pnp_device_id), "pnp",
Index: linux-2.6.22-rc4/drivers/acpi/scan.c
===================================================================
--- linux-2.6.22-rc4.orig/drivers/acpi/scan.c
+++ linux-2.6.22-rc4/drivers/acpi/scan.c
@@ -16,7 +16,7 @@ ACPI_MODULE_NAME("scan");
 extern struct acpi_device *acpi_root;
 
 #define ACPI_BUS_CLASS			"system_bus"
-#define ACPI_BUS_HID			"ACPI_BUS"
+#define ACPI_BUS_HID			"XBUS0001"
 #define ACPI_BUS_DEVICE_NAME		"System Bus"
 
 static LIST_HEAD(acpi_device_list);
@@ -29,6 +29,69 @@ struct acpi_device_bus_id{
 	unsigned int instance_no;
 	struct list_head node;
 };
+
+/*
+  Currently only handles ID strings, not compressed EISA, here the spec:
+
+  A _HID object evaluates to either a numeric 32-bit compressed EISA type ID
+  or a string. If a string, the format must be an alphanumeric PNP or ACPI ID
+  with no asterisk or other leading characters.
+
+  Why is hardware_id char[15] -> see include/acpi/acpi_bus.h ?!?
+
+  This function only handles devices correctly that have a HID.
+  If there are devices that have CID(s), but no HID work needs
+*/
+int create_modalias(struct acpi_device *acpi_dev, char *modalias, int size){
+
+	int len;
+
+	if (!acpi_dev->flags.hardware_id)
+		return -ENODEV;
+
+	len = snprintf(modalias, size, "acpi:%s:",
+		       acpi_dev->pnp.hardware_id);
+	if (len < 0 || len >= size)
+		return -EINVAL;
+	size -= len;
+
+	if (acpi_dev->flags.compatible_ids) {
+		struct acpi_compatible_id_list *cid_list;
+		int i;
+		int count;
+
+		cid_list = acpi_dev->pnp.cid_list;
+		for (i = 0; i < cid_list->count; i++) {
+			count = snprintf(&modalias[len], size, "%s:",
+					 cid_list->id[i].value);
+			if (count < 0 || count >= size) {
+				printk(KERN_ERR "acpi: %s cid[%i] exceeds event buffer size",
+				       acpi_dev->pnp.device_name, i);
+				break;
+			}
+			len += count;
+			size -= count;
+		}
+	}
+
+	modalias[len] = '\0';
+	return len;
+}
+
+static ssize_t
+acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) {
+	struct acpi_device *acpi_dev = to_acpi_device(dev);
+	int len;
+
+	/* Device has no HID and no CID or string is >1024 */
+	len = create_modalias(acpi_dev, buf, 1024);
+	if (len <= 0)
+		return 0;
+	buf[len++] = '\n';
+	return len;
+}
+static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL);
+
 static int acpi_eject_operation(acpi_handle handle, int lockable)
 {
 	struct acpi_object_list arg_list;
@@ -154,6 +217,12 @@ static int acpi_device_setup_files(struc
 			goto end;
 	}
 
+	if (dev->flags.hardware_id || dev->flags.compatible_ids){
+		result = device_create_file(&dev->dev, &dev_attr_modalias);
+		if(result)
+			goto end;
+	}
+
         /*
          * If device has _EJ0, 'eject' file is created that is used to trigger
          * hot-removal function from userland.
@@ -178,6 +247,9 @@ static void acpi_device_remove_files(str
 	if (ACPI_SUCCESS(status))
 		device_remove_file(&dev->dev, &dev_attr_eject);
 
+	if (dev->flags.hardware_id || dev->flags.compatible_ids)
+		device_remove_file(&dev->dev, &dev_attr_modalias);
+
 	if(dev->flags.hardware_id)
 		device_remove_file(&dev->dev, &dev_attr_hid);
 	if(dev->handle)
@@ -186,6 +258,37 @@ static void acpi_device_remove_files(str
 /* --------------------------------------------------------------------------
 			ACPI Bus operations
    -------------------------------------------------------------------------- */
+
+int acpi_match_device_ids(struct acpi_device *device,
+			  const struct acpi_device_id *ids)
+{
+	const struct acpi_device_id *id;
+
+	if (device->flags.hardware_id) {
+		for (id = ids; id->id[0]; id++) {
+			if (!strcmp((char*)id->id, device->pnp.hardware_id))
+				return 0;
+		}
+	}
+
+	if (device->flags.compatible_ids) {
+		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
+		int i;
+
+		for (id = ids; id->id[0]; id++) {
+			/* compare multiple _CID entries against driver ids */
+			for (i = 0; i < cid_list->count; i++) {
+				if (!strcmp((char*)id->id,
+					    cid_list->id[i].value))
+					return 0;
+			}
+		}
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(acpi_match_device_ids);
+
 static void acpi_device_release(struct device *dev)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -219,37 +322,19 @@ static int acpi_bus_match(struct device 
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 	struct acpi_driver *acpi_drv = to_acpi_driver(drv);
 
-	return !acpi_match_ids(acpi_dev, acpi_drv->ids);
+	return !acpi_match_device_ids(acpi_dev, acpi_drv->ids);
 }
 
 static int acpi_device_uevent(struct device *dev, char **envp, int num_envp,
-	char *buffer, int buffer_size)
+			      char *buffer, int buffer_size)
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
-	int i = 0, length = 0, ret = 0;
-
-	if (acpi_dev->flags.hardware_id)
-		ret = add_uevent_var(envp, num_envp, &i,
-			buffer, buffer_size, &length,
-			"HWID=%s", acpi_dev->pnp.hardware_id);
-	if (ret)
-		return -ENOMEM;
-	if (acpi_dev->flags.compatible_ids) {
-		int j;
-		struct acpi_compatible_id_list *cid_list;
 
-		cid_list = acpi_dev->pnp.cid_list;
-
-		for (j = 0; j < cid_list->count; j++) {
-			ret = add_uevent_var(envp, num_envp, &i, buffer,
-				buffer_size, &length, "COMPTID=%s",
-				cid_list->id[j].value);
-			if (ret)
-				return -ENOMEM;
-		}
+	strcpy(buffer, "MODALIAS=");
+	if (create_modalias(acpi_dev, buffer + 9, buffer_size - 9) > 0) {
+		envp[0] = buffer;
+		envp[1] = NULL;
 	}
-
-	envp[i] = NULL;
 	return 0;
 }
 
@@ -543,25 +628,6 @@ void acpi_bus_data_handler(acpi_handle h
 	return;
 }
 
-int acpi_match_ids(struct acpi_device *device, char *ids)
-{
-	if (device->flags.hardware_id)
-		if (strstr(ids, device->pnp.hardware_id))
-			return 0;
-
-	if (device->flags.compatible_ids) {
-		struct acpi_compatible_id_list *cid_list = device->pnp.cid_list;
-		int i;
-
-		/* compare multiple _CID entries against driver ids */
-		for (i = 0; i < cid_list->count; i++) {
-			if (strstr(ids, cid_list->id[i].value))
-				return 0;
-		}
-	}
-	return -ENOENT;
-}
-
 static int acpi_bus_get_perf_flags(struct acpi_device *device)
 {
 	device->performance.state = ACPI_STATE_UNKNOWN;
@@ -624,6 +690,13 @@ static int acpi_bus_get_wakeup_device_fl
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *package = NULL;
 
+	struct acpi_device_id button_device_ids[] = {
+		{"PNP0C0D", 0},
+		{"PNP0C0C", 0},
+		{"PNP0C0E", 0},
+		{"", 0},
+	};
+
 
 	/* _PRW */
 	status = acpi_evaluate_object(device->handle, "_PRW", NULL, &buffer);
@@ -643,7 +716,7 @@ static int acpi_bus_get_wakeup_device_fl
 
 	device->wakeup.flags.valid = 1;
 	/* Power button, Lid switch always enable wakeup */
-	if (!acpi_match_ids(device, "PNP0C0D,PNP0C0C,PNP0C0E"))
+	if (!acpi_match_device_ids(device, button_device_ids))
 		device->wakeup.flags.run_wake = 1;
 
       end:
Index: linux-2.6.22-rc4/drivers/pnp/pnpacpi/core.c
===================================================================
--- linux-2.6.22-rc4.orig/drivers/pnp/pnpacpi/core.c
+++ linux-2.6.22-rc4/drivers/pnp/pnpacpi/core.c
@@ -21,7 +21,10 @@
 
 #include <linux/acpi.h>
 #include <linux/pnp.h>
+#include <linux/mod_devicetable.h>
 #include <acpi/acpi_bus.h>
+#include <acpi/actypes.h>
+
 #include "pnpacpi.h"
 
 static int num = 0;
@@ -33,15 +36,17 @@ static int num = 0;
  * have irqs (PIC, Timer) because we call acpi_register_gsi.
  * Finaly only devices that have a CRS method need to be in this list.
  */
-static char __initdata excluded_id_list[] =
-	"PNP0C09," /* EC */
-	"PNP0C0F," /* Link device */
-	"PNP0000," /* PIC */
-	"PNP0100," /* Timer */
-	;
+static __initdata struct acpi_device_id excluded_id_list[] ={
+	{"PNP0C09", 0}, /* EC */
+	{"PNP0C0F", 0}, /* Link device */
+	{"PNP0000", 0}, /* PIC */
+	{"PNP0100", 0}, /* Timer */
+	{"", 0};
+};
+
 static inline int is_exclusive_device(struct acpi_device *dev)
 {
-	return (!acpi_match_ids(dev, excluded_id_list));
+	return (!acpi_match_device_ids(dev, excluded_id_list));
 }
 
 /*
Index: linux-2.6.22-rc4/include/linux/acpi.h
===================================================================
--- linux-2.6.22-rc4.orig/include/linux/acpi.h
+++ linux-2.6.22-rc4/include/linux/acpi.h
@@ -33,6 +33,7 @@
 #endif
 
 #include <linux/list.h>
+#include <linux/mod_devicetable.h>
 
 #include <acpi/acpi.h>
 #include <acpi/acpi_bus.h>


View attachment "acpi_autoloading_interface.patch" of type "text/x-patch" (10943 bytes)

Powered by blists - more mailing lists