xref: /linux/drivers/platform/x86/wmi.c (revision d39d0ed196aa1685bb24771e92f78633c66ac9cb)
1 /*
2  *  ACPI-WMI mapping driver
3  *
4  *  Copyright (C) 2007-2008 Carlos Corbacho <carlos@strangeworlds.co.uk>
5  *
6  *  GUID parsing code from ldm.c is:
7  *   Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
8  *   Copyright (c) 2001-2007 Anton Altaparmakov
9  *   Copyright (C) 2001,2002 Jakob Kemi <jakob.kemi@telia.com>
10  *
11  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License as published by
15  *  the Free Software Foundation; either version 2 of the License, or (at
16  *  your option) any later version.
17  *
18  *  This program is distributed in the hope that it will be useful, but
19  *  WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *  General Public License for more details.
22  *
23  *  You should have received a copy of the GNU General Public License along
24  *  with this program; if not, write to the Free Software Foundation, Inc.,
25  *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26  *
27  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
28  */
29 
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/types.h>
33 #include <linux/device.h>
34 #include <linux/list.h>
35 #include <linux/acpi.h>
36 #include <linux/slab.h>
37 #include <acpi/acpi_bus.h>
38 #include <acpi/acpi_drivers.h>
39 
40 ACPI_MODULE_NAME("wmi");
41 MODULE_AUTHOR("Carlos Corbacho");
42 MODULE_DESCRIPTION("ACPI-WMI Mapping Driver");
43 MODULE_LICENSE("GPL");
44 
45 #define ACPI_WMI_CLASS "wmi"
46 
47 #define PREFIX "ACPI: WMI: "
48 
49 static DEFINE_MUTEX(wmi_data_lock);
50 
51 struct guid_block {
52 	char guid[16];
53 	union {
54 		char object_id[2];
55 		struct {
56 			unsigned char notify_id;
57 			unsigned char reserved;
58 		};
59 	};
60 	u8 instance_count;
61 	u8 flags;
62 };
63 
64 struct wmi_block {
65 	struct list_head list;
66 	struct guid_block gblock;
67 	acpi_handle handle;
68 	wmi_notify_handler handler;
69 	void *handler_data;
70 	struct device *dev;
71 };
72 
73 static struct wmi_block wmi_blocks;
74 
75 /*
76  * If the GUID data block is marked as expensive, we must enable and
77  * explicitily disable data collection.
78  */
79 #define ACPI_WMI_EXPENSIVE   0x1
80 #define ACPI_WMI_METHOD      0x2	/* GUID is a method */
81 #define ACPI_WMI_STRING      0x4	/* GUID takes & returns a string */
82 #define ACPI_WMI_EVENT       0x8	/* GUID is an event */
83 
84 static int debug_event;
85 module_param(debug_event, bool, 0444);
86 MODULE_PARM_DESC(debug_event,
87 		 "Log WMI Events [0/1]");
88 
89 static int debug_dump_wdg;
90 module_param(debug_dump_wdg, bool, 0444);
91 MODULE_PARM_DESC(debug_dump_wdg,
92 		 "Dump available WMI interfaces [0/1]");
93 
94 static int acpi_wmi_remove(struct acpi_device *device, int type);
95 static int acpi_wmi_add(struct acpi_device *device);
96 static void acpi_wmi_notify(struct acpi_device *device, u32 event);
97 
98 static const struct acpi_device_id wmi_device_ids[] = {
99 	{"PNP0C14", 0},
100 	{"pnp0c14", 0},
101 	{"", 0},
102 };
103 MODULE_DEVICE_TABLE(acpi, wmi_device_ids);
104 
105 static struct acpi_driver acpi_wmi_driver = {
106 	.name = "wmi",
107 	.class = ACPI_WMI_CLASS,
108 	.ids = wmi_device_ids,
109 	.ops = {
110 		.add = acpi_wmi_add,
111 		.remove = acpi_wmi_remove,
112 		.notify = acpi_wmi_notify,
113 		},
114 };
115 
116 /*
117  * GUID parsing functions
118  */
119 
120 /**
121  * wmi_parse_hexbyte - Convert a ASCII hex number to a byte
122  * @src:  Pointer to at least 2 characters to convert.
123  *
124  * Convert a two character ASCII hex string to a number.
125  *
126  * Return:  0-255  Success, the byte was parsed correctly
127  *          -1     Error, an invalid character was supplied
128  */
129 static int wmi_parse_hexbyte(const u8 *src)
130 {
131 	unsigned int x; /* For correct wrapping */
132 	int h;
133 
134 	/* high part */
135 	x = src[0];
136 	if (x - '0' <= '9' - '0') {
137 		h = x - '0';
138 	} else if (x - 'a' <= 'f' - 'a') {
139 		h = x - 'a' + 10;
140 	} else if (x - 'A' <= 'F' - 'A') {
141 		h = x - 'A' + 10;
142 	} else {
143 		return -1;
144 	}
145 	h <<= 4;
146 
147 	/* low part */
148 	x = src[1];
149 	if (x - '0' <= '9' - '0')
150 		return h | (x - '0');
151 	if (x - 'a' <= 'f' - 'a')
152 		return h | (x - 'a' + 10);
153 	if (x - 'A' <= 'F' - 'A')
154 		return h | (x - 'A' + 10);
155 	return -1;
156 }
157 
158 /**
159  * wmi_swap_bytes - Rearrange GUID bytes to match GUID binary
160  * @src:   Memory block holding binary GUID (16 bytes)
161  * @dest:  Memory block to hold byte swapped binary GUID (16 bytes)
162  *
163  * Byte swap a binary GUID to match it's real GUID value
164  */
165 static void wmi_swap_bytes(u8 *src, u8 *dest)
166 {
167 	int i;
168 
169 	for (i = 0; i <= 3; i++)
170 		memcpy(dest + i, src + (3 - i), 1);
171 
172 	for (i = 0; i <= 1; i++)
173 		memcpy(dest + 4 + i, src + (5 - i), 1);
174 
175 	for (i = 0; i <= 1; i++)
176 		memcpy(dest + 6 + i, src + (7 - i), 1);
177 
178 	memcpy(dest + 8, src + 8, 8);
179 }
180 
181 /**
182  * wmi_parse_guid - Convert GUID from ASCII to binary
183  * @src:   36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
184  * @dest:  Memory block to hold binary GUID (16 bytes)
185  *
186  * N.B. The GUID need not be NULL terminated.
187  *
188  * Return:  'true'   @dest contains binary GUID
189  *          'false'  @dest contents are undefined
190  */
191 static bool wmi_parse_guid(const u8 *src, u8 *dest)
192 {
193 	static const int size[] = { 4, 2, 2, 2, 6 };
194 	int i, j, v;
195 
196 	if (src[8]  != '-' || src[13] != '-' ||
197 		src[18] != '-' || src[23] != '-')
198 		return false;
199 
200 	for (j = 0; j < 5; j++, src++) {
201 		for (i = 0; i < size[j]; i++, src += 2, *dest++ = v) {
202 			v = wmi_parse_hexbyte(src);
203 			if (v < 0)
204 				return false;
205 		}
206 	}
207 
208 	return true;
209 }
210 
211 /*
212  * Convert a raw GUID to the ACII string representation
213  */
214 static int wmi_gtoa(const char *in, char *out)
215 {
216 	int i;
217 
218 	for (i = 3; i >= 0; i--)
219 		out += sprintf(out, "%02X", in[i] & 0xFF);
220 
221 	out += sprintf(out, "-");
222 	out += sprintf(out, "%02X", in[5] & 0xFF);
223 	out += sprintf(out, "%02X", in[4] & 0xFF);
224 	out += sprintf(out, "-");
225 	out += sprintf(out, "%02X", in[7] & 0xFF);
226 	out += sprintf(out, "%02X", in[6] & 0xFF);
227 	out += sprintf(out, "-");
228 	out += sprintf(out, "%02X", in[8] & 0xFF);
229 	out += sprintf(out, "%02X", in[9] & 0xFF);
230 	out += sprintf(out, "-");
231 
232 	for (i = 10; i <= 15; i++)
233 		out += sprintf(out, "%02X", in[i] & 0xFF);
234 
235 	out = '\0';
236 	return 0;
237 }
238 
239 static bool find_guid(const char *guid_string, struct wmi_block **out)
240 {
241 	char tmp[16], guid_input[16];
242 	struct wmi_block *wblock;
243 	struct guid_block *block;
244 	struct list_head *p;
245 
246 	wmi_parse_guid(guid_string, tmp);
247 	wmi_swap_bytes(tmp, guid_input);
248 
249 	list_for_each(p, &wmi_blocks.list) {
250 		wblock = list_entry(p, struct wmi_block, list);
251 		block = &wblock->gblock;
252 
253 		if (memcmp(block->guid, guid_input, 16) == 0) {
254 			if (out)
255 				*out = wblock;
256 			return 1;
257 		}
258 	}
259 	return 0;
260 }
261 
262 static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable)
263 {
264 	struct guid_block *block = NULL;
265 	char method[5];
266 	struct acpi_object_list input;
267 	union acpi_object params[1];
268 	acpi_status status;
269 	acpi_handle handle;
270 
271 	block = &wblock->gblock;
272 	handle = wblock->handle;
273 
274 	if (!block)
275 		return AE_NOT_EXIST;
276 
277 	input.count = 1;
278 	input.pointer = params;
279 	params[0].type = ACPI_TYPE_INTEGER;
280 	params[0].integer.value = enable;
281 
282 	snprintf(method, 5, "WE%02X", block->notify_id);
283 	status = acpi_evaluate_object(handle, method, &input, NULL);
284 
285 	if (status != AE_OK && status != AE_NOT_FOUND)
286 		return status;
287 	else
288 		return AE_OK;
289 }
290 
291 /*
292  * Exported WMI functions
293  */
294 /**
295  * wmi_evaluate_method - Evaluate a WMI method
296  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
297  * @instance: Instance index
298  * @method_id: Method ID to call
299  * &in: Buffer containing input for the method call
300  * &out: Empty buffer to return the method results
301  *
302  * Call an ACPI-WMI method
303  */
304 acpi_status wmi_evaluate_method(const char *guid_string, u8 instance,
305 u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
306 {
307 	struct guid_block *block = NULL;
308 	struct wmi_block *wblock = NULL;
309 	acpi_handle handle;
310 	acpi_status status;
311 	struct acpi_object_list input;
312 	union acpi_object params[3];
313 	char method[5] = "WM";
314 
315 	if (!find_guid(guid_string, &wblock))
316 		return AE_ERROR;
317 
318 	block = &wblock->gblock;
319 	handle = wblock->handle;
320 
321 	if (!(block->flags & ACPI_WMI_METHOD))
322 		return AE_BAD_DATA;
323 
324 	if (block->instance_count < instance)
325 		return AE_BAD_PARAMETER;
326 
327 	input.count = 2;
328 	input.pointer = params;
329 	params[0].type = ACPI_TYPE_INTEGER;
330 	params[0].integer.value = instance;
331 	params[1].type = ACPI_TYPE_INTEGER;
332 	params[1].integer.value = method_id;
333 
334 	if (in) {
335 		input.count = 3;
336 
337 		if (block->flags & ACPI_WMI_STRING) {
338 			params[2].type = ACPI_TYPE_STRING;
339 		} else {
340 			params[2].type = ACPI_TYPE_BUFFER;
341 		}
342 		params[2].buffer.length = in->length;
343 		params[2].buffer.pointer = in->pointer;
344 	}
345 
346 	strncat(method, block->object_id, 2);
347 
348 	status = acpi_evaluate_object(handle, method, &input, out);
349 
350 	return status;
351 }
352 EXPORT_SYMBOL_GPL(wmi_evaluate_method);
353 
354 /**
355  * wmi_query_block - Return contents of a WMI block
356  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
357  * @instance: Instance index
358  * &out: Empty buffer to return the contents of the data block to
359  *
360  * Return the contents of an ACPI-WMI data block to a buffer
361  */
362 acpi_status wmi_query_block(const char *guid_string, u8 instance,
363 struct acpi_buffer *out)
364 {
365 	struct guid_block *block = NULL;
366 	struct wmi_block *wblock = NULL;
367 	acpi_handle handle, wc_handle;
368 	acpi_status status, wc_status = AE_ERROR;
369 	struct acpi_object_list input, wc_input;
370 	union acpi_object wc_params[1], wq_params[1];
371 	char method[5];
372 	char wc_method[5] = "WC";
373 
374 	if (!guid_string || !out)
375 		return AE_BAD_PARAMETER;
376 
377 	if (!find_guid(guid_string, &wblock))
378 		return AE_ERROR;
379 
380 	block = &wblock->gblock;
381 	handle = wblock->handle;
382 
383 	if (block->instance_count < instance)
384 		return AE_BAD_PARAMETER;
385 
386 	/* Check GUID is a data block */
387 	if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
388 		return AE_ERROR;
389 
390 	input.count = 1;
391 	input.pointer = wq_params;
392 	wq_params[0].type = ACPI_TYPE_INTEGER;
393 	wq_params[0].integer.value = instance;
394 
395 	/*
396 	 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to
397 	 * enable collection.
398 	 */
399 	if (block->flags & ACPI_WMI_EXPENSIVE) {
400 		wc_input.count = 1;
401 		wc_input.pointer = wc_params;
402 		wc_params[0].type = ACPI_TYPE_INTEGER;
403 		wc_params[0].integer.value = 1;
404 
405 		strncat(wc_method, block->object_id, 2);
406 
407 		/*
408 		 * Some GUIDs break the specification by declaring themselves
409 		 * expensive, but have no corresponding WCxx method. So we
410 		 * should not fail if this happens.
411 		 */
412 		wc_status = acpi_get_handle(handle, wc_method, &wc_handle);
413 		if (ACPI_SUCCESS(wc_status))
414 			wc_status = acpi_evaluate_object(handle, wc_method,
415 				&wc_input, NULL);
416 	}
417 
418 	strcpy(method, "WQ");
419 	strncat(method, block->object_id, 2);
420 
421 	status = acpi_evaluate_object(handle, method, &input, out);
422 
423 	/*
424 	 * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method, even if
425 	 * the WQxx method failed - we should disable collection anyway.
426 	 */
427 	if ((block->flags & ACPI_WMI_EXPENSIVE) && ACPI_SUCCESS(wc_status)) {
428 		wc_params[0].integer.value = 0;
429 		status = acpi_evaluate_object(handle,
430 		wc_method, &wc_input, NULL);
431 	}
432 
433 	return status;
434 }
435 EXPORT_SYMBOL_GPL(wmi_query_block);
436 
437 /**
438  * wmi_set_block - Write to a WMI block
439  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
440  * @instance: Instance index
441  * &in: Buffer containing new values for the data block
442  *
443  * Write the contents of the input buffer to an ACPI-WMI data block
444  */
445 acpi_status wmi_set_block(const char *guid_string, u8 instance,
446 const struct acpi_buffer *in)
447 {
448 	struct guid_block *block = NULL;
449 	struct wmi_block *wblock = NULL;
450 	acpi_handle handle;
451 	struct acpi_object_list input;
452 	union acpi_object params[2];
453 	char method[5] = "WS";
454 
455 	if (!guid_string || !in)
456 		return AE_BAD_DATA;
457 
458 	if (!find_guid(guid_string, &wblock))
459 		return AE_ERROR;
460 
461 	block = &wblock->gblock;
462 	handle = wblock->handle;
463 
464 	if (block->instance_count < instance)
465 		return AE_BAD_PARAMETER;
466 
467 	/* Check GUID is a data block */
468 	if (block->flags & (ACPI_WMI_EVENT | ACPI_WMI_METHOD))
469 		return AE_ERROR;
470 
471 	input.count = 2;
472 	input.pointer = params;
473 	params[0].type = ACPI_TYPE_INTEGER;
474 	params[0].integer.value = instance;
475 
476 	if (block->flags & ACPI_WMI_STRING) {
477 		params[1].type = ACPI_TYPE_STRING;
478 	} else {
479 		params[1].type = ACPI_TYPE_BUFFER;
480 	}
481 	params[1].buffer.length = in->length;
482 	params[1].buffer.pointer = in->pointer;
483 
484 	strncat(method, block->object_id, 2);
485 
486 	return acpi_evaluate_object(handle, method, &input, NULL);
487 }
488 EXPORT_SYMBOL_GPL(wmi_set_block);
489 
490 static void wmi_dump_wdg(struct guid_block *g)
491 {
492 	char guid_string[37];
493 
494 	wmi_gtoa(g->guid, guid_string);
495 	printk(KERN_INFO PREFIX "%s:\n", guid_string);
496 	printk(KERN_INFO PREFIX "\tobject_id: %c%c\n",
497 	       g->object_id[0], g->object_id[1]);
498 	printk(KERN_INFO PREFIX "\tnotify_id: %02X\n", g->notify_id);
499 	printk(KERN_INFO PREFIX "\treserved: %02X\n", g->reserved);
500 	printk(KERN_INFO PREFIX "\tinstance_count: %d\n", g->instance_count);
501 	printk(KERN_INFO PREFIX "\tflags: %#x", g->flags);
502 	if (g->flags) {
503 		printk(" ");
504 		if (g->flags & ACPI_WMI_EXPENSIVE)
505 			printk("ACPI_WMI_EXPENSIVE ");
506 		if (g->flags & ACPI_WMI_METHOD)
507 			printk("ACPI_WMI_METHOD ");
508 		if (g->flags & ACPI_WMI_STRING)
509 			printk("ACPI_WMI_STRING ");
510 		if (g->flags & ACPI_WMI_EVENT)
511 			printk("ACPI_WMI_EVENT ");
512 	}
513 	printk("\n");
514 
515 }
516 
517 static void wmi_notify_debug(u32 value, void *context)
518 {
519 	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
520 	union acpi_object *obj;
521 	acpi_status status;
522 
523 	status = wmi_get_event_data(value, &response);
524 	if (status != AE_OK) {
525 		printk(KERN_INFO "wmi: bad event status 0x%x\n", status);
526 		return;
527 	}
528 
529 	obj = (union acpi_object *)response.pointer;
530 
531 	if (!obj)
532 		return;
533 
534 	printk(KERN_INFO PREFIX "DEBUG Event ");
535 	switch(obj->type) {
536 	case ACPI_TYPE_BUFFER:
537 		printk("BUFFER_TYPE - length %d\n", obj->buffer.length);
538 		break;
539 	case ACPI_TYPE_STRING:
540 		printk("STRING_TYPE - %s\n", obj->string.pointer);
541 		break;
542 	case ACPI_TYPE_INTEGER:
543 		printk("INTEGER_TYPE - %llu\n", obj->integer.value);
544 		break;
545 	case ACPI_TYPE_PACKAGE:
546 		printk("PACKAGE_TYPE - %d elements\n", obj->package.count);
547 		break;
548 	default:
549 		printk("object type 0x%X\n", obj->type);
550 	}
551 	kfree(obj);
552 }
553 
554 /**
555  * wmi_install_notify_handler - Register handler for WMI events
556  * @handler: Function to handle notifications
557  * @data: Data to be returned to handler when event is fired
558  *
559  * Register a handler for events sent to the ACPI-WMI mapper device.
560  */
561 acpi_status wmi_install_notify_handler(const char *guid,
562 wmi_notify_handler handler, void *data)
563 {
564 	struct wmi_block *block;
565 	acpi_status status;
566 
567 	if (!guid || !handler)
568 		return AE_BAD_PARAMETER;
569 
570 	if (!find_guid(guid, &block))
571 		return AE_NOT_EXIST;
572 
573 	if (block->handler && block->handler != wmi_notify_debug)
574 		return AE_ALREADY_ACQUIRED;
575 
576 	block->handler = handler;
577 	block->handler_data = data;
578 
579 	status = wmi_method_enable(block, 1);
580 
581 	return status;
582 }
583 EXPORT_SYMBOL_GPL(wmi_install_notify_handler);
584 
585 /**
586  * wmi_uninstall_notify_handler - Unregister handler for WMI events
587  *
588  * Unregister handler for events sent to the ACPI-WMI mapper device.
589  */
590 acpi_status wmi_remove_notify_handler(const char *guid)
591 {
592 	struct wmi_block *block;
593 	acpi_status status = AE_OK;
594 
595 	if (!guid)
596 		return AE_BAD_PARAMETER;
597 
598 	if (!find_guid(guid, &block))
599 		return AE_NOT_EXIST;
600 
601 	if (!block->handler || block->handler == wmi_notify_debug)
602 		return AE_NULL_ENTRY;
603 
604 	if (debug_event) {
605 		block->handler = wmi_notify_debug;
606 	} else {
607 		status = wmi_method_enable(block, 0);
608 		block->handler = NULL;
609 		block->handler_data = NULL;
610 	}
611 	return status;
612 }
613 EXPORT_SYMBOL_GPL(wmi_remove_notify_handler);
614 
615 /**
616  * wmi_get_event_data - Get WMI data associated with an event
617  *
618  * @event: Event to find
619  * @out: Buffer to hold event data. out->pointer should be freed with kfree()
620  *
621  * Returns extra data associated with an event in WMI.
622  */
623 acpi_status wmi_get_event_data(u32 event, struct acpi_buffer *out)
624 {
625 	struct acpi_object_list input;
626 	union acpi_object params[1];
627 	struct guid_block *gblock;
628 	struct wmi_block *wblock;
629 	struct list_head *p;
630 
631 	input.count = 1;
632 	input.pointer = params;
633 	params[0].type = ACPI_TYPE_INTEGER;
634 	params[0].integer.value = event;
635 
636 	list_for_each(p, &wmi_blocks.list) {
637 		wblock = list_entry(p, struct wmi_block, list);
638 		gblock = &wblock->gblock;
639 
640 		if ((gblock->flags & ACPI_WMI_EVENT) &&
641 			(gblock->notify_id == event))
642 			return acpi_evaluate_object(wblock->handle, "_WED",
643 				&input, out);
644 	}
645 
646 	return AE_NOT_FOUND;
647 }
648 EXPORT_SYMBOL_GPL(wmi_get_event_data);
649 
650 /**
651  * wmi_has_guid - Check if a GUID is available
652  * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba
653  *
654  * Check if a given GUID is defined by _WDG
655  */
656 bool wmi_has_guid(const char *guid_string)
657 {
658 	return find_guid(guid_string, NULL);
659 }
660 EXPORT_SYMBOL_GPL(wmi_has_guid);
661 
662 /*
663  * sysfs interface
664  */
665 static ssize_t show_modalias(struct device *dev, struct device_attribute *attr,
666 			     char *buf)
667 {
668 	char guid_string[37];
669 	struct wmi_block *wblock;
670 
671 	wblock = dev_get_drvdata(dev);
672 	if (!wblock)
673 		return -ENOMEM;
674 
675 	wmi_gtoa(wblock->gblock.guid, guid_string);
676 
677 	return sprintf(buf, "wmi:%s\n", guid_string);
678 }
679 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
680 
681 static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env)
682 {
683 	char guid_string[37];
684 
685 	struct wmi_block *wblock;
686 
687 	if (add_uevent_var(env, "MODALIAS="))
688 		return -ENOMEM;
689 
690 	wblock = dev_get_drvdata(dev);
691 	if (!wblock)
692 		return -ENOMEM;
693 
694 	wmi_gtoa(wblock->gblock.guid, guid_string);
695 
696 	strcpy(&env->buf[env->buflen - 1], "wmi:");
697 	memcpy(&env->buf[env->buflen - 1 + 4], guid_string, 36);
698 	env->buflen += 40;
699 
700 	return 0;
701 }
702 
703 static void wmi_dev_free(struct device *dev)
704 {
705 	kfree(dev);
706 }
707 
708 static struct class wmi_class = {
709 	.name = "wmi",
710 	.dev_release = wmi_dev_free,
711 	.dev_uevent = wmi_dev_uevent,
712 };
713 
714 static int wmi_create_devs(void)
715 {
716 	int result;
717 	char guid_string[37];
718 	struct guid_block *gblock;
719 	struct wmi_block *wblock;
720 	struct list_head *p;
721 	struct device *guid_dev;
722 
723 	/* Create devices for all the GUIDs */
724 	list_for_each(p, &wmi_blocks.list) {
725 		wblock = list_entry(p, struct wmi_block, list);
726 
727 		guid_dev = kzalloc(sizeof(struct device), GFP_KERNEL);
728 		if (!guid_dev)
729 			return -ENOMEM;
730 
731 		wblock->dev = guid_dev;
732 
733 		guid_dev->class = &wmi_class;
734 		dev_set_drvdata(guid_dev, wblock);
735 
736 		gblock = &wblock->gblock;
737 
738 		wmi_gtoa(gblock->guid, guid_string);
739 		dev_set_name(guid_dev, guid_string);
740 
741 		result = device_register(guid_dev);
742 		if (result)
743 			return result;
744 
745 		result = device_create_file(guid_dev, &dev_attr_modalias);
746 		if (result)
747 			return result;
748 	}
749 
750 	return 0;
751 }
752 
753 static void wmi_remove_devs(void)
754 {
755 	struct guid_block *gblock;
756 	struct wmi_block *wblock;
757 	struct list_head *p;
758 	struct device *guid_dev;
759 
760 	/* Delete devices for all the GUIDs */
761 	list_for_each(p, &wmi_blocks.list) {
762 		wblock = list_entry(p, struct wmi_block, list);
763 
764 		guid_dev = wblock->dev;
765 		gblock = &wblock->gblock;
766 
767 		device_remove_file(guid_dev, &dev_attr_modalias);
768 
769 		device_unregister(guid_dev);
770 	}
771 }
772 
773 static void wmi_class_exit(void)
774 {
775 	wmi_remove_devs();
776 	class_unregister(&wmi_class);
777 }
778 
779 static int wmi_class_init(void)
780 {
781 	int ret;
782 
783 	ret = class_register(&wmi_class);
784 	if (ret)
785 		return ret;
786 
787 	ret = wmi_create_devs();
788 	if (ret)
789 		wmi_class_exit();
790 
791 	return ret;
792 }
793 
794 static bool guid_already_parsed(const char *guid_string)
795 {
796 	struct guid_block *gblock;
797 	struct wmi_block *wblock;
798 	struct list_head *p;
799 
800 	list_for_each(p, &wmi_blocks.list) {
801 		wblock = list_entry(p, struct wmi_block, list);
802 		gblock = &wblock->gblock;
803 
804 		if (strncmp(gblock->guid, guid_string, 16) == 0)
805 			return true;
806 	}
807 	return false;
808 }
809 
810 /*
811  * Parse the _WDG method for the GUID data blocks
812  */
813 static acpi_status parse_wdg(acpi_handle handle)
814 {
815 	struct acpi_buffer out = {ACPI_ALLOCATE_BUFFER, NULL};
816 	union acpi_object *obj;
817 	struct guid_block *gblock;
818 	struct wmi_block *wblock;
819 	char guid_string[37];
820 	acpi_status status;
821 	u32 i, total;
822 
823 	status = acpi_evaluate_object(handle, "_WDG", NULL, &out);
824 
825 	if (ACPI_FAILURE(status))
826 		return status;
827 
828 	obj = (union acpi_object *) out.pointer;
829 
830 	if (obj->type != ACPI_TYPE_BUFFER)
831 		return AE_ERROR;
832 
833 	total = obj->buffer.length / sizeof(struct guid_block);
834 
835 	gblock = kmemdup(obj->buffer.pointer, obj->buffer.length, GFP_KERNEL);
836 	if (!gblock) {
837 		status = AE_NO_MEMORY;
838 		goto out_free_pointer;
839 	}
840 
841 	for (i = 0; i < total; i++) {
842 		/*
843 		  Some WMI devices, like those for nVidia hooks, have a
844 		  duplicate GUID. It's not clear what we should do in this
845 		  case yet, so for now, we'll just ignore the duplicate.
846 		  Anyone who wants to add support for that device can come
847 		  up with a better workaround for the mess then.
848 		*/
849 		if (guid_already_parsed(gblock[i].guid) == true) {
850 			wmi_gtoa(gblock[i].guid, guid_string);
851 			printk(KERN_INFO PREFIX "Skipping duplicate GUID %s\n",
852 				guid_string);
853 			continue;
854 		}
855 		if (debug_dump_wdg)
856 			wmi_dump_wdg(&gblock[i]);
857 
858 		wblock = kzalloc(sizeof(struct wmi_block), GFP_KERNEL);
859 		if (!wblock) {
860 			status = AE_NO_MEMORY;
861 			goto out_free_gblock;
862 		}
863 
864 		wblock->gblock = gblock[i];
865 		wblock->handle = handle;
866 		if (debug_event) {
867 			wblock->handler = wmi_notify_debug;
868 			status = wmi_method_enable(wblock, 1);
869 		}
870 		list_add_tail(&wblock->list, &wmi_blocks.list);
871 	}
872 
873 out_free_gblock:
874 	kfree(gblock);
875 out_free_pointer:
876 	kfree(out.pointer);
877 
878 	return status;
879 }
880 
881 /*
882  * WMI can have EmbeddedControl access regions. In which case, we just want to
883  * hand these off to the EC driver.
884  */
885 static acpi_status
886 acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address,
887 		      u32 bits, u64 *value,
888 		      void *handler_context, void *region_context)
889 {
890 	int result = 0, i = 0;
891 	u8 temp = 0;
892 
893 	if ((address > 0xFF) || !value)
894 		return AE_BAD_PARAMETER;
895 
896 	if (function != ACPI_READ && function != ACPI_WRITE)
897 		return AE_BAD_PARAMETER;
898 
899 	if (bits != 8)
900 		return AE_BAD_PARAMETER;
901 
902 	if (function == ACPI_READ) {
903 		result = ec_read(address, &temp);
904 		(*value) |= ((u64)temp) << i;
905 	} else {
906 		temp = 0xff & ((*value) >> i);
907 		result = ec_write(address, temp);
908 	}
909 
910 	switch (result) {
911 	case -EINVAL:
912 		return AE_BAD_PARAMETER;
913 		break;
914 	case -ENODEV:
915 		return AE_NOT_FOUND;
916 		break;
917 	case -ETIME:
918 		return AE_TIME;
919 		break;
920 	default:
921 		return AE_OK;
922 	}
923 }
924 
925 static void acpi_wmi_notify(struct acpi_device *device, u32 event)
926 {
927 	struct guid_block *block;
928 	struct wmi_block *wblock;
929 	struct list_head *p;
930 	char guid_string[37];
931 
932 	list_for_each(p, &wmi_blocks.list) {
933 		wblock = list_entry(p, struct wmi_block, list);
934 		block = &wblock->gblock;
935 
936 		if ((block->flags & ACPI_WMI_EVENT) &&
937 			(block->notify_id == event)) {
938 			if (wblock->handler)
939 				wblock->handler(event, wblock->handler_data);
940 			if (debug_event) {
941 				wmi_gtoa(wblock->gblock.guid, guid_string);
942 				printk(KERN_INFO PREFIX "DEBUG Event GUID:"
943 				       " %s\n", guid_string);
944 			}
945 
946 			acpi_bus_generate_netlink_event(
947 				device->pnp.device_class, dev_name(&device->dev),
948 				event, 0);
949 			break;
950 		}
951 	}
952 }
953 
954 static int acpi_wmi_remove(struct acpi_device *device, int type)
955 {
956 	acpi_remove_address_space_handler(device->handle,
957 				ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler);
958 
959 	return 0;
960 }
961 
962 static int acpi_wmi_add(struct acpi_device *device)
963 {
964 	acpi_status status;
965 	int result = 0;
966 
967 	status = acpi_install_address_space_handler(device->handle,
968 						    ACPI_ADR_SPACE_EC,
969 						    &acpi_wmi_ec_space_handler,
970 						    NULL, NULL);
971 	if (ACPI_FAILURE(status))
972 		return -ENODEV;
973 
974 	status = parse_wdg(device->handle);
975 	if (ACPI_FAILURE(status)) {
976 		printk(KERN_ERR PREFIX "Error installing EC region handler\n");
977 		return -ENODEV;
978 	}
979 
980 	return result;
981 }
982 
983 static int __init acpi_wmi_init(void)
984 {
985 	int result;
986 
987 	INIT_LIST_HEAD(&wmi_blocks.list);
988 
989 	if (acpi_disabled)
990 		return -ENODEV;
991 
992 	result = acpi_bus_register_driver(&acpi_wmi_driver);
993 
994 	if (result < 0) {
995 		printk(KERN_INFO PREFIX "Error loading mapper\n");
996 		return -ENODEV;
997 	}
998 
999 	result = wmi_class_init();
1000 	if (result) {
1001 		acpi_bus_unregister_driver(&acpi_wmi_driver);
1002 		return result;
1003 	}
1004 
1005 	printk(KERN_INFO PREFIX "Mapper loaded\n");
1006 
1007 	return result;
1008 }
1009 
1010 static void __exit acpi_wmi_exit(void)
1011 {
1012 	struct list_head *p, *tmp;
1013 	struct wmi_block *wblock;
1014 
1015 	wmi_class_exit();
1016 
1017 	acpi_bus_unregister_driver(&acpi_wmi_driver);
1018 
1019 	list_for_each_safe(p, tmp, &wmi_blocks.list) {
1020 		wblock = list_entry(p, struct wmi_block, list);
1021 
1022 		list_del(p);
1023 		kfree(wblock);
1024 	}
1025 
1026 	printk(KERN_INFO PREFIX "Mapper unloaded\n");
1027 }
1028 
1029 subsys_initcall(acpi_wmi_init);
1030 module_exit(acpi_wmi_exit);
1031