ACPI: WMI: Add WMI-ACPI mapper driver
PATCH v4 1/1 ACPI: WMI: Add WMI-ACPI mapper driver
From: Carlos Corbacho <[email protected]>
The following is an implementation of the Windows Management Instrumentation (WMI) ACPI interface mapper (PNP0C14).
What it does:
Parses the _WDG method and exports functions to process WMI method calls, data block query/ set commands (both based on GUID) and does basic event handling.
i.e.
wmi_evaluate_method(const char *guid, u32 instance, u32 method_id, const struct acpi_buffer *in, struct acpi_buffer *out)
wmi_query_block(const char *guid, u32 instance,
struct acpi_buffer *out)
wmi_set_block(const char *guid, u32 instance,
const struct acpi_buffer *in)
It also provides a helper method to find if a GUID exists or not on the system (a quick and easy way for WMI dependant drivers to see if the the method/ block they want exists, since GUIDs are supposed to be unique).
i.e.
bool wmi_has_guid(const char guid*)
Where guid is the text encoding of the guid, e.g.:
"67C3371D-95A3-4C37-BB61-DD47B491DAAB"
Event handling - allow a WMI based driver to register a notifier handler with WMI. When a notification is sent to WMI, WMI will execute _WED and then pass the results and the event to the external handler (since WMI does not know the meaning of an event, it is left to the external drivers to deal with, rather than WMI exporting the event to userspace).
What it might be able to do:
Handle reading data block GUIDs marked as "expensive" (e.g. calling WCxx with the correct arguments, before and after querying the block in question). My DSDT does not have any such marked block methods, so this is untested.
What it can't do:
Unicode - The MS article[1] calls for converting between ASCII and Unicode (or vice versa) if a GUID is marked as "string". There is also another problem in that given this specification revolves around Windows, Unicode in this context likely means UTF-16. Since Linux doesn't use this, and since this driver will only be called by other Linux drivers, it may make more sense to treat Unicode here as UTF-8 instead.
What it won't do:
Handle a MOF[1] - the WMI mapper just implements simple calls that are wrappers around ACPI functions. Also, MOFs are based around the Windows WMI API, so they make little sense on Linux.
Userspace - the WMI mapper disregards the WMI-ACPI spec on this point, and does _not_ try to export to userspace, since WMI does not exist on Linux. All callers of the WMI mapper are assumed to be kernel space drivers.
[1] http://www.microsoft.com/whdc/system/pnppwr/wmi/wmi-acpi.mspx
===
ChangeLog
==
v1 (2007-10-02):
* Initial release
v2 (2007-10-05):
* Cleaned up code - split up super "wmi_evaluate_block" -> each external symbol now handles its own ACPI calls, rather than handing off to a "super" method (and in turn, is a lot simpler to read)
* Added a find_guid() symbol - return true if a given GUID exists on the system
* wmi_* functions now return type acpi_status (since they are just fancy wrappers around acpi_evaluate_object())
* Removed extra debug code
v3 (2007-10-27)
* More code clean up - now passes checkpatch.pl
* Change data block calls - ref MS spec, method ID is not required for them, so drop it from the function parameters.
* Const'ify guid in the function call parameters.
* Fix _WDG buffer handling - copy the data to our own private structure.
* Change WMI from tristate to bool - otherwise the external functions are not exported in linux/acpi.h if you try to build WMI as a module.
* Fix more flag comparisons.
* Add a maintainers entry - since I wrote this, I should take the blame for it.
v4 (2007-10-30)
* Add missing brace from after fixing checkpatch errors.
* Rewrote event handling - allow external drivers to register with WMI to handle WMI events
* Clean up flags and sanitise flag handling
--- MAINTAINERS | 7 + drivers/acpi/Kconfig | 11 + drivers/acpi/Makefile | 1 + drivers/acpi/wmi.c | 590 +++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/acpi.h | 17 ++ 5 files changed, 626 insertions(+), 0 deletions(-) create mode 100644 drivers/acpi/wmi.c
MAINTAINERS +7 -0
@@ -261,6 +261,13 @@ L: [email protected] W: http://acpi.sourceforge.net/ S: Supported +ACPI WMI DRIVER +P: Carlos Corbacho +M: [email protected] +L: [email protected] +W: http://www.lesswatts.org/projects/acpi/ +S: Supported + ADM1025 HARDWARE MONITOR DRIVER P: Jean Delvare M: [email protected]
drivers/acpi/Kconfig +11 -0
@@ -179,6 +179,17 @@ config ACPI_NUMA depends on (X86 || IA64) default y if IA64_GENERIC || IA64_SGI_SN2 +config ACPI_WMI + bool "WMI (EXPERIMENTAL)" + depends on EXPERIMENTAL + default y + help + This driver adds support for the WMI ACPI mapper device (PNP0C14) + found on some systems. + + NOTE: You will need another driver on top of this to actually use + anything defined in the WMI ACPI device. + config ACPI_ASUS tristate "ASUS/Medion Laptop Extras" depends on X86
drivers/acpi/Makefile +1 -0
@@ -55,6 +55,7 @@ obj-$(CONFIG_ACPI_THERMAL) += thermal.o obj-$(CONFIG_ACPI_SYSTEM) += system.o event.o obj-$(CONFIG_ACPI_DEBUG) += debug.o obj-$(CONFIG_ACPI_NUMA) += numa.o +obj-$(CONFIG_ACPI_WMI) += wmi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
drivers/acpi/wmi.c new file +590 -0
590 lines not on this page · raw message
include/linux/acpi.h +17 -0
@@ -186,6 +186,23 @@ extern int ec_transaction(u8 command,#endif /*CONFIG_ACPI_EC*/ +#ifdef CONFIG_ACPI_WMI + +extern acpi_status wmi_evaluate_method (const char *guid,u32 instance, +u32 method_id, +const struct acpi_buffer *in, +struct acpi_buffer *out); +extern acpi_status wmi_query_block (const char *guid,u32 instance, +struct acpi_buffer *out); +extern acpi_status wmi_set_block (const char *guid,u32 instance, +const struct acpi_buffer *in); +extern acpi_status wmi_install_notify_handler (acpi_notify_handler handler, +struct acpi_buffer *data); +extern acpi_status wmi_remove_notify_handler (void ); +extern bool wmi_has_guid (const char *guid); + +#endif /* CONFIG_ACPI_WMI */ +extern int acpi_blacklisted (void );extern void acpi_bios_year (char *s);
Signature · 1 line
1.5.3.4
Quoted 5 lines · Carlos Corbacho
Event handling - allow a WMI based driver to register a notifier handler with WMI. When a notification is sent to WMI, WMI will execute
_WEDand then pass the results and the event to the external handler (since WMI does not know the meaning of an event, it is left to the external drivers to deal with, rather than WMI exporting the event to userspace).
I suspect that for a lot of cases, exporting this to userspace would be helpful - it's often easier for us to do this mapping in hal and just push out an updated fdi file than it would be to push out an updated kernel driver.
Quoted 3 lines
Userspace - the WMI mapper disregards the WMI-ACPI spec on this point, and does _not_ try to export to userspace, since WMI does not exist on Linux. All callers of the WMI mapper are assumed to be kernel space drivers.
And for similar reasons, I think it would be helpful to provide userspace with the ability to trigger WMI calls. It's going to be easier for people to add GUIDs to a userspace file than to extend a kernel driver, even if there are some cases that are better handled by having a full in-kernel driver.
Signature · 1 line
Matthew Garrett | [email protected]
Quoted 4 lines · On Tuesday 30 Otober 2007 13:47:01 Matthew Garrett wrote:
I suspect that for a lot of cases, exporting this to userspace would be helpful - it's often easier for us to do this mapping in hal and just push out an updated fdi file than it would be to push out an updated kernel driver.
But what would be mapped via HAL?
WMI is such a completely undefined "standard", that not only do you have to map the GUIDs, but you'd also have to map the program logic as well (marshalling arguments, restricting function parameters, call order, etc) and this strikes me as being beyond the scope of an fdi file.
For some methods, which are quite simple, this _might_ be possible. For others I've seen, this will end up a complete mess.
If you're going to do all that, you may as well write a driver in kernel space and leave that to export the functionality in a way userspace can already handle.
Quoted 5 lines
And for similar reasons, I think it would be helpful to provide userspace with the ability to trigger WMI calls. It's going to be easier for people to add GUIDs to a userspace file than to extend a kernel driver, even if there are some cases that are better handled by having a full in-kernel driver.
There are also other technical problems with this, beyond my own personal disagreement - since WMI relies so heavily on ACPI (well, the driver here is really just a simple wrapper), then you would have to start exporting bits of ACPI to userspace to access WMI. As mentioned in the original patches - the mapper knows nothing about "types", this knowledge is known only by the caller - WMI just deals in acpi_buffer. My understanding is that ACPI would have to export the required functions and data structures so that userspace could provide then translate from acpi_buffer to the known type (unless there is another way round this to import and export the data to/ from userspace?)
-Carlos
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D
Quoted 10 lines · On Tuesday 30 October 2007 14:28:10 Carlos Corbacho wrote:
There are also other technical problems with this, beyond my own personal disagreement - since WMI relies so heavily on ACPI (well, the driver here is really just a simple wrapper), then you would have to start exporting bits of ACPI to userspace to access WMI. As mentioned in the original patches - the mapper knows nothing about "types", this knowledge is known only by the caller - WMI just deals in
acpi_buffer. My understanding is that ACPI would have to export the required functions and data structures so that userspace could provide then translate fromacpi_bufferto the known type (unless there is another way round this to import and export the data to/ from userspace?)
To backtrack slightly - I'm wrong on this point; after sleeping on this for the night (and/ or application of cluebat), I can modify the functions to let userspace call them without exporting half of ACPI in the process.
However, I still believe that HAL is the wrong application to deal with WMI.
-Carlos
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D
Len Brown
reviewerWhen I consulted Anas about WMI, he recommended that Linux expose WMI via CIMOM. I think that this means we'd need to invent a sysfs interface for this acpi->wmi driver to expose the hooks to a user-space daemon, which would then make sense of it in Linux's management framework.
Anas provided the references below.
thanks,
-Len
http://developer.novell.com/wiki/index.php/OMC
This is a Novell project with many providers dealing will many aspects of the OS. They also provide RPMs for OpenSUSE and is the main source for the OpenWBEM CIMOM binaries for SUSE.
http://sblim.wiki.sourceforge.net/
Is the IBM project dealing with instrumentation and home of the SFCB CIMOM targeting embedded environments and only supports CMPI providers.
http://sblim.wiki.sourceforge.net/ProviderCmpiSysfs is a sysfs provider. Seems to be old but is a good example.
This is the home of the OpenPeagsus CIMOM, supported by multiple vendors.
http://www.dmtf.org/standards/wbem/ is about the WBEM protocol. Also the tutorial is good: http://www.wbemsolutions.com/tutorials/CIM/wbem.html
http://cimple.org/ tries to make writing providers easy.
Quoted 5 lines · On Tuesday 30 October 2007 18:18:22 Len Brown wrote:
When I consulted Anas about WMI, he recommended that Linux expose WMI via CIMOM. I think that this means we'd need to invent a sysfs interface for this
acpi->wmidriver to expose the hooks to a user-space daemon, which would then make sense of it in Linux's management framework.
The main problem to overcome with a sysfs interface is that a WMI-ACPI call takes multiple values (worst case scenario is a method, which takes three arguments - method id, instance and an input buffer).
We could try and do something like this for methods & data blocks:
/sys/firmware/acpi/wmi/<GUID>/ ->
type (method, event, data)instance_count (maximum number of instances - method's & data only)
Then have the following directory for each possible instance:
/sys/firmware/acpi/wmi/<GUID>/<instance>/
Inside, we'd have two files:
method_id (methods only)
data
For data blocks, it's easy -> just read/ write from data (wmi.c could also try to be clever, and set the correct read/ write permissions by checking for appropriate methods).
For method calling -> This is more complicated, since we need to pass a method id and the input data (and unlike instance, WMI-ACPI does not define the maximum number of methods). We could do this by writing to a file called method_id first with the method_id we want to call, then read/ write to data (but I'm open to suggestions for a better interface).
Events would, I imagine, be some sort of polling, although probably split over two files:
One file to tell the polling application of the event, another file (say 'data'), containing the data associated with that event?
Unless there's another way we can export the events without polling?
-Carlos
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D
Quoted 11 lines · On Tuesday 30 October 2007 22:52:30 Carlos Corbacho wrote:
Quoted 5 lines · On Tuesday 30 October 2007 18:18:22 Len Brown wrote:
When I consulted Anas about WMI, he recommended that Linux expose WMI via CIMOM. I think that this means we'd need to invent a sysfs interface for this
acpi->wmidriver to expose the hooks to a user-space daemon, which would then make sense of it in Linux's management framework.The main problem to overcome with a sysfs interface is that a WMI-ACPI call takes multiple values (worst case scenario is a method, which takes three arguments - method id, instance and an input buffer).
Also, for input, I don't know how to handle the size/ type problem[1] - only this user-space daemon would know what size/ type of buffer the input requires (via the relevant MOF in the management framework) - this information would also need to be conveyed through the sysfs interface to the mapper somehow.
e.g. If we write '1' (assume we have already set the method id somehow) to /sys/firmware/acpi/wmi/<guid>/<instance>/data
What type/ size is the correct size of the buffer parameter to be passed to ACPI - u8 (1 byte), u16 (2 bytes), u32 (4 bytes), etc?
So, thinking this over more carefully, whilst sysfs can probably be used to export data, I'm not entirely convinced for using it to input arbitrary data types, unless there's some way we can get round this?
-Carlos
[1] For a buffer to be passed to acpi_evaluate_object() as a parameter, we must know the size in bytes to use beforehand when we create the buffer - otherwise, if we pass an incorrectly sized buffer as a parameter, the acpi_evaluate_object() call will fail. However, WMI-ACPI does not specify this - so this information is known only to the MOF writer, or caller of the WMI method/ data set.
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D
Quoted 8 lines · On Wednesday 31 October 2007 00:18:19 Carlos Corbacho wrote:
Quoted 7 lines · On Tuesday 30 October 2007 22:52:30 Carlos Corbacho wrote:
Quoted 5 lines · On Tuesday 30 October 2007 18:18:22 Len Brown wrote:
When I consulted Anas about WMI, he recommended that Linux expose WMI via CIMOM. I think that this means we'd need to invent a sysfs interface for this
acpi->wmidriver to expose the hooks to a user-space daemon, which would then make sense of it in Linux's management framework.
Quoted 6 lines
Quoted 2 lines
The main problem to overcome with a sysfs interface is that a WMI-ACPI call takes multiple values.
So, thinking this over more carefully, whilst sysfs can probably be used to export data, I'm not entirely convinced for using it to input arbitrary data types, unless there's some way we can get round this?
After sleeping on the matter, I'm now certain that sysfs is the wrong way to go for allowing userspace to access WMI-ACPI - we're trying to pass and return too much data for sysfs to handle.
So, what we can do is modify the proposed internal kernel calls for userspace (since a little sleep is a wonderful thing) to something like:
wmi_evaluate_method(const char* guid, __u32 instance, __u32 method id, void *input, __u32 input_size, void *output, __u32 output_size)
(wmi_evaluate_method could be shrunk to just _one_ buffer, since the WMI-ACPI spec suggests the mapper should only take & return one buffer).
wmi_query_data(const char* guid, __u32 instance, void *output, __u32 output_size)
wmi_set_data(const char* guid, __u32 instance, void *input, __u32 input_size)
(Event handling is a little more tricky - we could create a
new 'wmi_event_handler', and allow userspace or in kernel drivers to register this handler with the WMI-ACPI mapper, and avoid polling).
Then, we leave it up to OpenWBEM, etc to write their own backend to handle WMI-ACPI (I'm not sure if "provider" is the right terminology to use with WMI-ACPI, since we're just converting WMI calls to ACPI). This backend would take a WMI-ACPI method call, and convert that to the correct kernel function call (the kernel function then handles making the ACPI call and returning the results). Interpretation is left to the backend and its associated MOF.
(For the case of WMI not being built in, we define all the functions to return an error, or if WMI is enabled but there is no WMI-ACPI mapping device, wmi.c would return the errors instead).
Would this be an acceptable solution? (Len - If this is the case, where do we expose the wmi_* functions to userspace? linux/acpi.h, or create a new include file?)
-Carlos
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D
Quoted 12 lines · On Wednesday 31 October 2007 12:21:10 Carlos Corbacho wrote:
Quoted 11 lines · On Wednesday 31 October 2007 00:18:19 Carlos Corbacho wrote:
Quoted 9 lines · On Tuesday 30 October 2007 22:52:30 Carlos Corbacho wrote:
Quoted 5 lines · On Tuesday 30 October 2007 18:18:22 Len Brown wrote:
When I consulted Anas about WMI, he recommended that Linux expose WMI via CIMOM. I think that this means we'd need to invent a sysfs interface for this
acpi->wmidriver to expose the hooks to a user-space daemon, which would then make sense of it in Linux's management framework.The main problem to overcome with a sysfs interface is that a WMI-ACPI call takes multiple values.
Quoted 7 lines
Quoted 3 lines
So, thinking this over more carefully, whilst sysfs can probably be used to export data, I'm not entirely convinced for using it to input arbitrary data types, unless there's some way we can get round this?
After sleeping on the matter, I'm now certain that sysfs is the wrong way to go for allowing userspace to access WMI-ACPI - we're trying to pass and return too much data for sysfs to handle.
On second thoughts, my other proposal won't work either - we'd end up with a mess of either ioctl's or sysctl's to call from userspace (I really should read up on my userspace interaction a bit more).
The sysfs proposal could be made to work, it will just be a little cumbersome (I'll have a go at implementing it and see how it works out).
-Carlos
Signature · 3 lines
E-Mail: [email protected] Web: strangeworlds.co.uk GPG Key ID: 0x23EE722D