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