diff mbox

[15/16] platform/x86: wmi-mof: New driver to expose embedded WMI MOF metadata

Message ID 27758381c6cb77efab75a266e21243a964cce0ba.1495862272.git.dvhart@infradead.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Darren Hart May 27, 2017, 5:31 a.m. UTC
From: Andy Lutomirski <luto@kernel.org>

Quite a few laptops (and maybe servers?) have embedded WMI MOF
metadata. I think that Samba has tools to interpret it, but there is
currently no interface to get the data in the first place.

In most cases, the MOF can be read out of the DSDT, but that is
non-compliant and messy.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Mario Limonciello <mario_limonciello@dell.com>
Cc: Pali Rohár <pali.rohar@gmail.com>
Cc: Rafael Wysocki <rjw@rjwysocki.net>
Cc: linux-kernel@vger.kernel.org
Cc: platform-driver-x86@vger.kernel.org
Cc: linux-acpi@vger.kernel.org
[dvhart: make sysfs mof binary read only, fixup comment block format]
Signed-off-by: Darren Hart (VMware) <dvhart@infradead.org>
---
 drivers/platform/x86/Kconfig   |  12 ++++
 drivers/platform/x86/Makefile  |   1 +
 drivers/platform/x86/wmi-mof.c | 125 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 138 insertions(+)
 create mode 100644 drivers/platform/x86/wmi-mof.c

Comments

Pali Rohár May 27, 2017, 11:14 a.m. UTC | #1
Hi! Note that in WMI is stored binary MOF (BMOF; .bmf file; compiled 
MOF), not ordinary MOF data which are plain text. So maybe it could make 
sense to include "B" into name of sysfs entry? Or not? (Just suggestion)

On Saturday 27 May 2017 07:31:29 Darren Hart wrote:
> From: Andy Lutomirski <luto@kernel.org>
> 
> Quite a few laptops (and maybe servers?) have embedded WMI MOF

Not "a few", but "lots of" :-)

> metadata. I think that Samba has tools to interpret it, but there is
> currently no interface to get the data in the first place.

No, there is no non-ms-windows tool for interpreting those binary MOF 
(BMF) data yet.

> +	priv->mofdata = wmidev_block_query(wdev, 0);
> +	if (!priv->mofdata) {
> +		dev_warn(&wdev->dev, "failed to read MOF\n");
> +		return -EIO;
> +	}
> +
> +	if (priv->mofdata->type != ACPI_TYPE_BUFFER) {
> +		dev_warn(&wdev->dev, "MOF is not a buffer\n");
> +		ret = -EIO;
> +		goto err_free;
> +	}

Are not those problems fatal for driver and therefore dev_err() better?

> +	sysfs_bin_attr_init(&priv->mof_bin_attr);
> +	priv->mof_bin_attr.attr.name = "mof";
> +	priv->mof_bin_attr.attr.mode = 0400;

0400 means to be readable only by root? Is there then reason why normal 
user should not be able to read it?
Andy Lutomirski May 27, 2017, 9:07 p.m. UTC | #2
On Sat, May 27, 2017 at 4:14 AM, Pali Rohár <pali.rohar@gmail.com> wrote:
> Hi! Note that in WMI is stored binary MOF (BMOF; .bmf file; compiled
> MOF), not ordinary MOF data which are plain text. So maybe it could make
> sense to include "B" into name of sysfs entry? Or not? (Just suggestion)
>
> On Saturday 27 May 2017 07:31:29 Darren Hart wrote:
>> From: Andy Lutomirski <luto@kernel.org>
>>
>> Quite a few laptops (and maybe servers?) have embedded WMI MOF
>
> Not "a few", but "lots of" :-)
>
>> metadata. I think that Samba has tools to interpret it, but there is
>> currently no interface to get the data in the first place.
>
> No, there is no non-ms-windows tool for interpreting those binary MOF
> (BMF) data yet.
>
>> +     priv->mofdata = wmidev_block_query(wdev, 0);
>> +     if (!priv->mofdata) {
>> +             dev_warn(&wdev->dev, "failed to read MOF\n");
>> +             return -EIO;
>> +     }
>> +
>> +     if (priv->mofdata->type != ACPI_TYPE_BUFFER) {
>> +             dev_warn(&wdev->dev, "MOF is not a buffer\n");
>> +             ret = -EIO;
>> +             goto err_free;
>> +     }
>
> Are not those problems fatal for driver and therefore dev_err() better?
>
>> +     sysfs_bin_attr_init(&priv->mof_bin_attr);
>> +     priv->mof_bin_attr.attr.name = "mof";
>> +     priv->mof_bin_attr.attr.mode = 0400;
>
> 0400 means to be readable only by root? Is there then reason why normal
> user should not be able to read it?
>

I have no specific objection to making it 0444, but in general I'd
rather expose less information to unprivileged users rather than more.
I'm also having trouble imagining what an unprivileged user would do
with the MOF -- it's useful for reverse engineering and it may
eventually be useful for making WMI calls from userspace, but neither
of those is particularly useful to unprivileged users.
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andy Shevchenko May 30, 2017, 3:24 p.m. UTC | #3
On Sat, 2017-05-27 at 14:07 -0700, Andy Lutomirski wrote:
> On Sat, May 27, 2017 at 4:14 AM, Pali Rohár <pali.rohar@gmail.com>
> wrote:
> > > Quite a few laptops (and maybe servers?) have embedded WMI MOF
> > 
> > Not "a few", but "lots of" :-)

Aren't they are synonyms ("quite a few" vs "lots of")?
Darren Hart May 30, 2017, 4:46 p.m. UTC | #4
On Tue, May 30, 2017 at 06:24:54PM +0300, Andy Shevchenko wrote:
> On Sat, 2017-05-27 at 14:07 -0700, Andy Lutomirski wrote:
> > On Sat, May 27, 2017 at 4:14 AM, Pali Rohár <pali.rohar@gmail.com>
> > wrote:
> > > > Quite a few laptops (and maybe servers?) have embedded WMI MOF
> > > 
> > > Not "a few", but "lots of" :-)
> 
> Aren't they are synonyms ("quite a few" vs "lots of")?

The difference is subtle enough that people we can probably get several
different answers, but generally yes. I'm happy to update it in any case.
Pali Rohár May 30, 2017, 5:03 p.m. UTC | #5
On Tuesday 30 May 2017 17:24:54 Andy Shevchenko wrote:
> On Sat, 2017-05-27 at 14:07 -0700, Andy Lutomirski wrote:
> > On Sat, May 27, 2017 at 4:14 AM, Pali Rohár <pali.rohar@gmail.com>
> > 
> > wrote:
> > > > Quite a few laptops (and maybe servers?) have embedded WMI MOF
> > > 
> > > Not "a few", but "lots of" :-)
> 
> Aren't they are synonyms ("quite a few" vs "lots of")?

I understand "lots of" > "quite a few" > "a few". And synonyms do not 
have exact meaning...

But now I was told that "quite a few" has emphasise meaning "more then 
expected".

For me it is normal fact that there are lot of machines with WMI. But if 
meaning in commit message should be "I'm surprise how many machines are 
with WMI", then "quite a few" better fit.

So choose what you prefer or want...
Andy Shevchenko May 30, 2017, 5:21 p.m. UTC | #6
On Tue, May 30, 2017 at 8:03 PM, Pali Rohár <pali.rohar@gmail.com> wrote:
> On Tuesday 30 May 2017 17:24:54 Andy Shevchenko wrote:
>> On Sat, 2017-05-27 at 14:07 -0700, Andy Lutomirski wrote:
>> > On Sat, May 27, 2017 at 4:14 AM, Pali Rohár <pali.rohar@gmail.com>
>> > wrote:

>> > > > Quite a few laptops (and maybe servers?) have embedded WMI MOF
>> > > Not "a few", but "lots of" :-)
>> Aren't they are synonyms ("quite a few" vs "lots of")?
>
> I understand "lots of" > "quite a few" > "a few". And synonyms do not
> have exact meaning...

I figured those two:

100% quite a lot -->> 50% <<-- quite a few 0%, which means (for my
understanding)
that with lim (n→∞) both are = 50% (n represents cases of use the terms).

> So choose what you prefer or want...

Same here!
Darren Hart June 5, 2017, 10:14 p.m. UTC | #7
On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:
> Hi! Note that in WMI is stored binary MOF (BMOF; .bmf file; compiled 
> MOF), not ordinary MOF data which are plain text. So maybe it could make 
> sense to include "B" into name of sysfs entry? Or not? (Just suggestion)

Did some digging, and .... yeah, you're right.

I've replaced with MOF with Binary MOF or bmof throughout the patch. Will resend
in a v2. Thanks.

> 
> On Saturday 27 May 2017 07:31:29 Darren Hart wrote:
> > From: Andy Lutomirski <luto@kernel.org>
> > 
> > Quite a few laptops (and maybe servers?) have embedded WMI MOF
> 
> Not "a few", but "lots of" :-)

I'll just use "Many" and save us continued debate :-)

> 
> > metadata. I think that Samba has tools to interpret it, but there is
> > currently no interface to get the data in the first place.
> 
> No, there is no non-ms-windows tool for interpreting those binary MOF 
> (BMF) data yet.

Good point. Updated.

> 
> > +	priv->mofdata = wmidev_block_query(wdev, 0);
> > +	if (!priv->mofdata) {
> > +		dev_warn(&wdev->dev, "failed to read MOF\n");
> > +		return -EIO;
> > +	}
> > +
> > +	if (priv->mofdata->type != ACPI_TYPE_BUFFER) {
> > +		dev_warn(&wdev->dev, "MOF is not a buffer\n");
> > +		ret = -EIO;
> > +		goto err_free;
> > +	}
> 
> Are not those problems fatal for driver and therefore dev_err() better?
> 

Yes, agreed. Updated.

> > +	sysfs_bin_attr_init(&priv->mof_bin_attr);
> > +	priv->mof_bin_attr.attr.name = "mof";
> > +	priv->mof_bin_attr.attr.mode = 0400;
> 
> 0400 means to be readable only by root? Is there then reason why normal 
> user should not be able to read it?
> 

We can always open access up, harder to lock it down later. Let's start with
this and adjust if necessary.
Pali Rohár June 5, 2017, 10:19 p.m. UTC | #8
On Tuesday 06 June 2017 00:14:56 Darren Hart wrote:
> On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:
> > > metadata. I think that Samba has tools to interpret it, but there
> > > is currently no interface to get the data in the first place.
> > 
> > No, there is no non-ms-windows tool for interpreting those binary
> > MOF (BMF) data yet.
> 
> Good point. Updated.

You are too late :-) Now there is my at https://github.com/pali/bmfdec 
See my email "Binary MOF buffer in WMI is finally decoded!".
Andy Lutomirski June 5, 2017, 10:39 p.m. UTC | #9
On Mon, Jun 5, 2017 at 3:19 PM, Pali Rohár <pali.rohar@gmail.com> wrote:
> On Tuesday 06 June 2017 00:14:56 Darren Hart wrote:
>> On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:
>> > > metadata. I think that Samba has tools to interpret it, but there
>> > > is currently no interface to get the data in the first place.
>> >
>> > No, there is no non-ms-windows tool for interpreting those binary
>> > MOF (BMF) data yet.
>>
>> Good point. Updated.
>
> You are too late :-) Now there is my at https://github.com/pali/bmfdec
> See my email "Binary MOF buffer in WMI is finally decoded!".
>

It comes out like this on my laptop.  I don't know enough about MOF to
know what we're supposed to do with this, but I suspect it at least
gives us the sizes of buffers that we should be passing to the various
methods.

class WMIEvent : __ExtrinsicEvent {
};

[WMI, Locale("MS\0x409"), Description("QDATA"),
guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")]
class QDat {
  [WmiDataId(1), read, write, Description("qdata")] uint8 Bytes[128];
};

[WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
Description("BIOS WMI Query"),
guid("{8D9DDCBC-A997-11DA-B012-B622A1EF5492}")]
class WMI_Query {
  [key, read] String InstanceName;
  [read] Boolean Active;
  [WmiDataId(1), read, write, Description("BIOS WMI info")] QDat QDATA;
};

[WMI, Locale("MS\0x409"), Description("Data"),
guid("{a3776ce0-1e88-11db-a98b-0800200c9a66}")]
class BDat {
  [WmiDataId(1), read, write, Description("data")] uint8 Bytes[4096];
};

[WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
Description("Interface"),
guid("{A80593CE-A997-11DA-B012-B622A1EF5492}")]
class BFn {
  [key, read] String InstanceName;
  [read] Boolean Active;

  [WmiMethodId(1), Implemented, read, write, Description("Do BFn")]
void DoBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,
Description("Fn buf"), ID(0)] BDat Data);
};

[WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
Description("Event"), guid("{9DBB5994-A997-11DA-B012-B622A1EF5492}")]
class BIOSEvent : WmiEvent {
  [key, read] String InstanceName;
  [read] Boolean Active;
  [WmiDataId(1), read, write, Description("Ev buf")] QDat Data;
};
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Darren Hart June 6, 2017, 2:33 a.m. UTC | #10
On Tue, Jun 06, 2017 at 12:19:26AM +0200, Pali Rohár wrote:
> On Tuesday 06 June 2017 00:14:56 Darren Hart wrote:
> > On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:
> > > > metadata. I think that Samba has tools to interpret it, but there
> > > > is currently no interface to get the data in the first place.
> > > 
> > > No, there is no non-ms-windows tool for interpreting those binary
> > > MOF (BMF) data yet.
> > 
> > Good point. Updated.
> 
> You are too late :-) Now there is my at https://github.com/pali/bmfdec 
> See my email "Binary MOF buffer in WMI is finally decoded!".

I've seen it, nice work. Will spend more time on it once I get the v2 for this
out the door.
Pali Rohár June 6, 2017, 11:05 a.m. UTC | #11
On Monday 05 June 2017 15:39:44 Andy Lutomirski wrote:
> On Mon, Jun 5, 2017 at 3:19 PM, Pali Rohár <pali.rohar@gmail.com> wrote:
> > On Tuesday 06 June 2017 00:14:56 Darren Hart wrote:
> >> On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:
> >> > > metadata. I think that Samba has tools to interpret it, but there
> >> > > is currently no interface to get the data in the first place.
> >> >
> >> > No, there is no non-ms-windows tool for interpreting those binary
> >> > MOF (BMF) data yet.
> >>
> >> Good point. Updated.
> >
> > You are too late :-) Now there is my at https://github.com/pali/bmfdec
> > See my email "Binary MOF buffer in WMI is finally decoded!".
> >
> 
> It comes out like this on my laptop.  I don't know enough about MOF to
> know what we're supposed to do with this, but I suspect it at least
> gives us the sizes of buffers that we should be passing to the various
> methods.

There are two tools bmfparse and bmf2mof. Difference is just output
format.

Important are WmiDataId and WmiMethodId qualifiers. Those define ids are
what are passed to kernel function wmi_evaluate_method(). Ids are
processed by corresponding WMxx ACPI function.

So instead of

  wmi_evaluate_method(guid, instance, method_id, acpi_in, acpi_out);

it should be possible to call:

  wmi_evaluate_method_name(class, name, input_params, output_params);

(once somebody implement wmi_evaluate_method_name function)

It is more readable in code to use class and function names instead of
some guids and random meaningless numbers. Also it would allow to check
size of input buffer (or types).

E.g.

  BDat data_in;
  BDat data_out;
  // fill data_in.Bytes
  wmi_evaluate_method_name("BFn", "DoBFn", &data_in, &data_out);
  // output is in data_out.Bytes

could be translated to:

  wmi_evaluate_method("A80593CE-A997-11DA-B012-B622A1EF5492", 0, 1, acpi_in, acpi_out);

Sometimes method_id is random number and hard to guess it. One of
possible solution is to trace ACPI calls on Windows, another is decode
that BMOF buffer and take correct method_id.

I will probably write another one tool which prints just important WMI
functions and their mapping to WMI ids + input/output parameters.
Without all other MOF data which are not relevant to ACPI-WMI.

> class WMIEvent : __ExtrinsicEvent {
> };
> 
> [WMI, Locale("MS\0x409"), Description("QDATA"),
> guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")]
> class QDat {
>   [WmiDataId(1), read, write, Description("qdata")] uint8 Bytes[128];
> };
> 
> [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
> Description("BIOS WMI Query"),
> guid("{8D9DDCBC-A997-11DA-B012-B622A1EF5492}")]
> class WMI_Query {
>   [key, read] String InstanceName;
>   [read] Boolean Active;
>   [WmiDataId(1), read, write, Description("BIOS WMI info")] QDat QDATA;
> };
> 
> [WMI, Locale("MS\0x409"), Description("Data"),
> guid("{a3776ce0-1e88-11db-a98b-0800200c9a66}")]
> class BDat {
>   [WmiDataId(1), read, write, Description("data")] uint8 Bytes[4096];
> };
> 
> [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
> Description("Interface"),
> guid("{A80593CE-A997-11DA-B012-B622A1EF5492}")]
> class BFn {
>   [key, read] String InstanceName;
>   [read] Boolean Active;
> 
>   [WmiMethodId(1), Implemented, read, write, Description("Do BFn")]
> void DoBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,
> Description("Fn buf"), ID(0)] BDat Data);
> };
> 
> [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),
> Description("Event"), guid("{9DBB5994-A997-11DA-B012-B622A1EF5492}")]
> class BIOSEvent : WmiEvent {
>   [key, read] String InstanceName;
>   [read] Boolean Active;
>   [WmiDataId(1), read, write, Description("Ev buf")] QDat Data;
> };
Limonciello, Mario June 6, 2017, 1:46 p.m. UTC | #12
Pali,

Amazing job with what you've done so far.  A few comments I wanted to share from my taking look at your bmf2mof and comparing to "source" MOF.
1) At least in source the case used for String and Boolean is lower case.  I'm unsure if that actually matters for any MOF parsing tools, but I wanted to FYI in case it does.
2) On my system when you expand the arguments for "void DoBFn" the source doesn't describe individual arguments like you do.  
Again this might not matter to MOF parsing tools but wanted to let you know in case it does.

source:
	void DoBFn([in, out, Description("Fn buf")] BDat Data);
bmf2mof:
	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out, Description("Fn buf"), ID(0)] BDat Data);

> -----Original Message-----

> From: Pali Rohár [mailto:pali.rohar@gmail.com]

> Sent: Tuesday, June 6, 2017 6:06 AM

> To: Andy Lutomirski <luto@amacapital.net>

> Cc: Darren Hart <dvhart@infradead.org>; platform-driver-x86@vger.kernel.org;

> Andy Shevchenko <andriy.shevchenko@linux.intel.com>; Andy Lutomirski

> <luto@kernel.org>; Limonciello, Mario <Mario_Limonciello@Dell.com>; Rafael

> Wysocki <rjw@rjwysocki.net>; linux-kernel@vger.kernel.org; Linux ACPI <linux-

> acpi@vger.kernel.org>

> Subject: Re: [PATCH 15/16] platform/x86: wmi-mof: New driver to expose

> embedded WMI MOF metadata

> 

> On Monday 05 June 2017 15:39:44 Andy Lutomirski wrote:

> > On Mon, Jun 5, 2017 at 3:19 PM, Pali Rohár <pali.rohar@gmail.com> wrote:

> > > On Tuesday 06 June 2017 00:14:56 Darren Hart wrote:

> > >> On Sat, May 27, 2017 at 01:14:15PM +0200, Pali Rohár wrote:

> > >> > > metadata. I think that Samba has tools to interpret it, but there

> > >> > > is currently no interface to get the data in the first place.

> > >> >

> > >> > No, there is no non-ms-windows tool for interpreting those binary

> > >> > MOF (BMF) data yet.

> > >>

> > >> Good point. Updated.

> > >

> > > You are too late :-) Now there is my at https://github.com/pali/bmfdec

> > > See my email "Binary MOF buffer in WMI is finally decoded!".

> > >

> >

> > It comes out like this on my laptop.  I don't know enough about MOF to

> > know what we're supposed to do with this, but I suspect it at least

> > gives us the sizes of buffers that we should be passing to the various

> > methods.

> 


Yes, the size of the buffers and the format of the data you can pass in them is 
what is most important bit of information that comes out of this.

> There are two tools bmfparse and bmf2mof. Difference is just output

> format.

> 

> Important are WmiDataId and WmiMethodId qualifiers. Those define ids are

> what are passed to kernel function wmi_evaluate_method(). Ids are

> processed by corresponding WMxx ACPI function.

> 

> So instead of

> 

>   wmi_evaluate_method(guid, instance, method_id, acpi_in, acpi_out);

> 

> it should be possible to call:

> 

>   wmi_evaluate_method_name(class, name, input_params, output_params);

> 

> (once somebody implement wmi_evaluate_method_name function)

> 

Now that you have managed to decode binary MOF, it might actually change
what makes sense to export to userspace.  We were previously
discussing exporting GUID's (eg  something like /dev/wmi-$GUID)
but with readable names that actually map to the GUID's, it makes more sense
to export the classes.  Userspace tools can parse the exported MOF to know
how to interact with those classes, and the classes can then map to chardevices.
For example on a Dell system today /dev/wmi-BFn would be the most important
to export (this will change in the future).

> It is more readable in code to use class and function names instead of

> some guids and random meaningless numbers. Also it would allow to check

> size of input buffer (or types).

Completely agree.  Once the parser can be brought into kernel, this is a very
good next change for existing WMI drivers.

> 

> E.g.

> 

>   BDat data_in;

>   BDat data_out;

>   // fill data_in.Bytes

>   wmi_evaluate_method_name("BFn", "DoBFn", &data_in, &data_out);

>   // output is in data_out.Bytes

> 

> could be translated to:

> 

>   wmi_evaluate_method("A80593CE-A997-11DA-B012-B622A1EF5492", 0, 1,

> acpi_in, acpi_out);

> 

> Sometimes method_id is random number and hard to guess it. One of

> possible solution is to trace ACPI calls on Windows, another is decode

> that BMOF buffer and take correct method_id.

> 

> I will probably write another one tool which prints just important WMI

> functions and their mapping to WMI ids + input/output parameters.

> Without all other MOF data which are not relevant to ACPI-WMI.


When this goes into the kernel, I think it would be ideal to export MOF
exactly like your bmf2mof does.
The userspace MOF parsing tools that already exist will be able to process 
it more effectively this way.
Perhaps internally in the kernel this mapping information will be useful to 
be able to  create wmi_evaluate_method_name.

> 

> > class WMIEvent : __ExtrinsicEvent {

> > };

> >

> > [WMI, Locale("MS\0x409"), Description("QDATA"),

> > guid("{ABBC0F60-8EA1-11d1-00A0-C90629100000}")]

> > class QDat {

> >   [WmiDataId(1), read, write, Description("qdata")] uint8 Bytes[128];

> > };

> >

> > [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),

> > Description("BIOS WMI Query"),

> > guid("{8D9DDCBC-A997-11DA-B012-B622A1EF5492}")]

> > class WMI_Query {

> >   [key, read] String InstanceName;

> >   [read] Boolean Active;

> >   [WmiDataId(1), read, write, Description("BIOS WMI info")] QDat QDATA;

> > };

> >

> > [WMI, Locale("MS\0x409"), Description("Data"),

> > guid("{a3776ce0-1e88-11db-a98b-0800200c9a66}")]

> > class BDat {

> >   [WmiDataId(1), read, write, Description("data")] uint8 Bytes[4096];

> > };

> >

> > [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),

> > Description("Interface"),

> > guid("{A80593CE-A997-11DA-B012-B622A1EF5492}")]

> > class BFn {

> >   [key, read] String InstanceName;

> >   [read] Boolean Active;

> >

> >   [WmiMethodId(1), Implemented, read, write, Description("Do BFn")]

> > void DoBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,

> > Description("Fn buf"), ID(0)] BDat Data);

> > };

> >

> > [WMI, Dynamic, Provider("WmiProv"), Locale("MS\0x409"),

> > Description("Event"), guid("{9DBB5994-A997-11DA-B012-B622A1EF5492}")]

> > class BIOSEvent : WmiEvent {

> >   [key, read] String InstanceName;

> >   [read] Boolean Active;

> >   [WmiDataId(1), read, write, Description("Ev buf")] QDat Data;

> > };

> 

> --

> Pali Rohár

> pali.rohar@gmail.com
Pali Rohár June 6, 2017, 1:56 p.m. UTC | #13
On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com wrote:
> Pali,
> 
> Amazing job with what you've done so far.  A few comments I wanted to share from my taking look at your bmf2mof and comparing to "source" MOF.
> 1) At least in source the case used for String and Boolean is lower case.  I'm unsure if that actually matters for any MOF parsing tools, but I wanted to FYI in case it does.

In MS documentation is String, Boolean and Datetime with first char
uppercase. But looks like mofcomp accept both upper case and lower case
variants.

> 2) On my system when you expand the arguments for "void DoBFn" the source doesn't describe individual arguments like you do.  
> Again this might not matter to MOF parsing tools but wanted to let you know in case it does.

I know, this part is missing. Order of arguments are only in ID
qualifier and not sorted + in/out de-duplicated.

> source:
> 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> bmf2mof:
> 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out, Description("Fn buf"), ID(0)] BDat Data);
Pali Rohár June 7, 2017, 5:39 p.m. UTC | #14
On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:
> On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com wrote:
> > 2) On my system when you expand the arguments for "void DoBFn" the
> > source doesn't describe individual arguments like you do. Again
> > this might not matter to MOF parsing tools but wanted to let you
> > know in case it does.
> 
> I know, this part is missing. Order of arguments are only in ID
> qualifier and not sorted + in/out de-duplicated.

Implemented! Now arguments are correctly placed based on ID qualifier.

> > source:
> > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > 
> > bmf2mof:
> > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,
> > 	Description("Fn buf"), ID(0)] BDat Data);
Limonciello, Mario June 7, 2017, 8:23 p.m. UTC | #15
> -----Original Message-----

> From: Pali Rohár [mailto:pali.rohar@gmail.com]

> Sent: Wednesday, June 7, 2017 12:39 PM

> To: Limonciello, Mario <Mario_Limonciello@Dell.com>

> Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-

> x86@vger.kernel.org; andriy.shevchenko@linux.intel.com; luto@kernel.org;

> rjw@rjwysocki.net; linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org

> Subject: Re: [PATCH 15/16] platform/x86: wmi-mof: New driver to expose

> embedded WMI MOF metadata

> 

> On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:

> > On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com wrote:

> > > 2) On my system when you expand the arguments for "void DoBFn" the

> > > source doesn't describe individual arguments like you do. Again

> > > this might not matter to MOF parsing tools but wanted to let you

> > > know in case it does.

> >

> > I know, this part is missing. Order of arguments are only in ID

> > qualifier and not sorted + in/out de-duplicated.

> 

> Implemented! Now arguments are correctly placed based on ID qualifier.

I think it's still off a little though.

What I'm getting back now from bmf2mof is:
	void DoBFn([in, Description("Fn buf"), out] BDat Data);

Whereas source puts Description as the last argument: 
	void DoBFn([in, out, Description("Fn buf")] BDat Data);

> 

> > > source:

> > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);

> > >

> > > bmf2mof:

> > > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,

> > > 	Description("Fn buf"), ID(0)] BDat Data);

> 

> --

> Pali Rohár

> pali.rohar@gmail.com
Pali Rohár June 7, 2017, 8:50 p.m. UTC | #16
On Wednesday 07 June 2017 22:23:08 Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Pali Rohár [mailto:pali.rohar@gmail.com]
> > Sent: Wednesday, June 7, 2017 12:39 PM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-
> > x86@vger.kernel.org; andriy.shevchenko@linux.intel.com;
> > luto@kernel.org; rjw@rjwysocki.net; linux-kernel@vger.kernel.org;
> > linux-acpi@vger.kernel.org Subject: Re: [PATCH 15/16]
> > platform/x86: wmi-mof: New driver to expose embedded WMI MOF
> > metadata
> > 
> > On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:
> > > On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com wrote:
> > > > 2) On my system when you expand the arguments for "void DoBFn"
> > > > the source doesn't describe individual arguments like you do.
> > > > Again this might not matter to MOF parsing tools but wanted to
> > > > let you know in case it does.
> > > 
> > > I know, this part is missing. Order of arguments are only in ID
> > > qualifier and not sorted + in/out de-duplicated.
> > 
> > Implemented! Now arguments are correctly placed based on ID
> > qualifier.
> 
> I think it's still off a little though.
> 
> What I'm getting back now from bmf2mof is:
> 	void DoBFn([in, Description("Fn buf"), out] BDat Data);
> 
> Whereas source puts Description as the last argument:
> 	void DoBFn([in, out, Description("Fn buf")] BDat Data);

In BMOF from my Latitude E6440 there are specified two parameters with 
index 0. One with qualifiers ("in", Description("Fn buf")) and one with 
("out", Description("Fn buf")). I think you have similar/same data in 
BMOF.

In my bmf2mof I just combined those two parameters into one (when name, 
type and index matches) and concatenate also qualifiers with removing 
duplicates.

Do not know what is correct way, but I think qualifiers are just 
unordered set. MS decompiler probably put "in" and "out" qualifiers 
before any other for better readability.

> > > > source:
> > > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > > > 
> > > > bmf2mof:
> > > > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,
> > > > 	Description("Fn buf"), ID(0)] BDat Data);
> > 
> > --
> > Pali Rohár
> > pali.rohar@gmail.com
Limonciello, Mario June 9, 2017, 3:46 p.m. UTC | #17
> -----Original Message-----

> From: Pali Rohár [mailto:pali.rohar@gmail.com]

> Sent: Wednesday, June 7, 2017 3:50 PM

> To: Limonciello, Mario <Mario_Limonciello@Dell.com>

> Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-

> x86@vger.kernel.org; andriy.shevchenko@linux.intel.com; luto@kernel.org;

> rjw@rjwysocki.net; linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org

> Subject: Re: [PATCH 15/16] platform/x86: wmi-mof: New driver to expose

> embedded WMI MOF metadata

> 

> On Wednesday 07 June 2017 22:23:08 Mario.Limonciello@dell.com wrote:

> > > -----Original Message-----

> > > From: Pali Rohár [mailto:pali.rohar@gmail.com]

> > > Sent: Wednesday, June 7, 2017 12:39 PM

> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>

> > > Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-

> > > x86@vger.kernel.org; andriy.shevchenko@linux.intel.com;

> > > luto@kernel.org; rjw@rjwysocki.net; linux-kernel@vger.kernel.org;

> > > linux-acpi@vger.kernel.org Subject: Re: [PATCH 15/16]

> > > platform/x86: wmi-mof: New driver to expose embedded WMI MOF

> > > metadata

> > >

> > > On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:

> > > > On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com wrote:

> > > > > 2) On my system when you expand the arguments for "void DoBFn"

> > > > > the source doesn't describe individual arguments like you do.

> > > > > Again this might not matter to MOF parsing tools but wanted to

> > > > > let you know in case it does.

> > > >

> > > > I know, this part is missing. Order of arguments are only in ID

> > > > qualifier and not sorted + in/out de-duplicated.

> > >

> > > Implemented! Now arguments are correctly placed based on ID

> > > qualifier.

> >

> > I think it's still off a little though.

> >

> > What I'm getting back now from bmf2mof is:

> > 	void DoBFn([in, Description("Fn buf"), out] BDat Data);

> >

> > Whereas source puts Description as the last argument:

> > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);

> 

> In BMOF from my Latitude E6440 there are specified two parameters with

> index 0. One with qualifiers ("in", Description("Fn buf")) and one with

> ("out", Description("Fn buf")). I think you have similar/same data in

> BMOF.

> 

> In my bmf2mof I just combined those two parameters into one (when name,

> type and index matches) and concatenate also qualifiers with removing

> duplicates.

> 

> Do not know what is correct way, but I think qualifiers are just

> unordered set. MS decompiler probably put "in" and "out" qualifiers

> before any other for better readability.


Have you tried to run it through mofcomp.exe and then decompile again
with bmf2mof?  As long as it's coming out the same you're probably right.

> 

> > > > > source:

> > > > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);

> > > > >

> > > > > bmf2mof:

> > > > > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data, [out,

> > > > > 	Description("Fn buf"), ID(0)] BDat Data);

> > >

> > > --

> > > Pali Rohár

> > > pali.rohar@gmail.com

> 

> --

> Pali Rohár

> pali.rohar@gmail.com
Pali Rohár June 9, 2017, 9:51 p.m. UTC | #18
On Friday 09 June 2017 17:46:12 Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Pali Rohár [mailto:pali.rohar@gmail.com]
> > Sent: Wednesday, June 7, 2017 3:50 PM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-
> > x86@vger.kernel.org; andriy.shevchenko@linux.intel.com;
> > luto@kernel.org; rjw@rjwysocki.net; linux-kernel@vger.kernel.org;
> > linux-acpi@vger.kernel.org Subject: Re: [PATCH 15/16]
> > platform/x86: wmi-mof: New driver to expose embedded WMI MOF
> > metadata
> > 
> > On Wednesday 07 June 2017 22:23:08 Mario.Limonciello@dell.com wrote:
> > > > -----Original Message-----
> > > > From: Pali Rohár [mailto:pali.rohar@gmail.com]
> > > > Sent: Wednesday, June 7, 2017 12:39 PM
> > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-
> > > > x86@vger.kernel.org; andriy.shevchenko@linux.intel.com;
> > > > luto@kernel.org; rjw@rjwysocki.net;
> > > > linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org
> > > > Subject: Re: [PATCH 15/16]
> > > > platform/x86: wmi-mof: New driver to expose embedded WMI MOF
> > > > metadata
> > > > 
> > > > On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:
> > > > > On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com
> > > > > wrote:
> > > > > > 2) On my system when you expand the arguments for "void
> > > > > > DoBFn" the source doesn't describe individual arguments
> > > > > > like you do. Again this might not matter to MOF parsing
> > > > > > tools but wanted to let you know in case it does.
> > > > > 
> > > > > I know, this part is missing. Order of arguments are only in
> > > > > ID qualifier and not sorted + in/out de-duplicated.
> > > > 
> > > > Implemented! Now arguments are correctly placed based on ID
> > > > qualifier.
> > > 
> > > I think it's still off a little though.
> > > 
> > > What I'm getting back now from bmf2mof is:
> > > 	void DoBFn([in, Description("Fn buf"), out] BDat Data);
> > > 
> > > Whereas source puts Description as the last argument:
> > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > 
> > In BMOF from my Latitude E6440 there are specified two parameters
> > with index 0. One with qualifiers ("in", Description("Fn buf"))
> > and one with ("out", Description("Fn buf")). I think you have
> > similar/same data in BMOF.
> > 
> > In my bmf2mof I just combined those two parameters into one (when
> > name, type and index matches) and concatenate also qualifiers with
> > removing duplicates.
> > 
> > Do not know what is correct way, but I think qualifiers are just
> > unordered set. MS decompiler probably put "in" and "out" qualifiers
> > before any other for better readability.
> 
> Have you tried to run it through mofcomp.exe and then decompile again
> with bmf2mof?  As long as it's coming out the same you're probably
> right.

Yes, bmf2mof+mofcomp.exe+bmf2mof gives same output as just bmf2mof.

> > > > > > source:
> > > > > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > > > > > 
> > > > > > bmf2mof:
> > > > > > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat Data,
> > > > > > 	[out, Description("Fn buf"), ID(0)] BDat Data);
> > > > 
> > > > --
> > > > Pali Rohár
> > > > pali.rohar@gmail.com
> > 
> > --
> > Pali Rohár
> > pali.rohar@gmail.com
Pali Rohár June 15, 2017, 4:46 p.m. UTC | #19
On Friday 09 June 2017 23:51:32 Pali Rohár wrote:
> On Friday 09 June 2017 17:46:12 Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Pali Rohár [mailto:pali.rohar@gmail.com]
> > > Sent: Wednesday, June 7, 2017 3:50 PM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: luto@amacapital.net; dvhart@infradead.org; platform-driver-
> > > x86@vger.kernel.org; andriy.shevchenko@linux.intel.com;
> > > luto@kernel.org; rjw@rjwysocki.net; linux-kernel@vger.kernel.org;
> > > linux-acpi@vger.kernel.org Subject: Re: [PATCH 15/16]
> > > platform/x86: wmi-mof: New driver to expose embedded WMI MOF
> > > metadata
> > > 
> > > On Wednesday 07 June 2017 22:23:08 Mario.Limonciello@dell.com
> > > wrote:
> > > > > -----Original Message-----
> > > > > From: Pali Rohár [mailto:pali.rohar@gmail.com]
> > > > > Sent: Wednesday, June 7, 2017 12:39 PM
> > > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > > Cc: luto@amacapital.net; dvhart@infradead.org;
> > > > > platform-driver- x86@vger.kernel.org;
> > > > > andriy.shevchenko@linux.intel.com; luto@kernel.org;
> > > > > rjw@rjwysocki.net;
> > > > > linux-kernel@vger.kernel.org; linux-acpi@vger.kernel.org
> > > > > Subject: Re: [PATCH 15/16]
> > > > > platform/x86: wmi-mof: New driver to expose embedded WMI MOF
> > > > > metadata
> > > > > 
> > > > > On Tuesday 06 June 2017 15:56:21 Pali Rohár wrote:
> > > > > > On Tuesday 06 June 2017 13:46:16 Mario.Limonciello@dell.com
> > > > > > 
> > > > > > wrote:
> > > > > > > 2) On my system when you expand the arguments for "void
> > > > > > > DoBFn" the source doesn't describe individual arguments
> > > > > > > like you do. Again this might not matter to MOF parsing
> > > > > > > tools but wanted to let you know in case it does.
> > > > > > 
> > > > > > I know, this part is missing. Order of arguments are only
> > > > > > in ID qualifier and not sorted + in/out de-duplicated.
> > > > > 
> > > > > Implemented! Now arguments are correctly placed based on ID
> > > > > qualifier.
> > > > 
> > > > I think it's still off a little though.
> > > > 
> > > > What I'm getting back now from bmf2mof is:
> > > > 	void DoBFn([in, Description("Fn buf"), out] BDat Data);
> > > > 
> > > > Whereas source puts Description as the last argument:
> > > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > > 
> > > In BMOF from my Latitude E6440 there are specified two parameters
> > > with index 0. One with qualifiers ("in", Description("Fn buf"))
> > > and one with ("out", Description("Fn buf")). I think you have
> > > similar/same data in BMOF.
> > > 
> > > In my bmf2mof I just combined those two parameters into one (when
> > > name, type and index matches) and concatenate also qualifiers
> > > with removing duplicates.
> > > 
> > > Do not know what is correct way, but I think qualifiers are just
> > > unordered set. MS decompiler probably put "in" and "out"
> > > qualifiers before any other for better readability.
> > 
> > Have you tried to run it through mofcomp.exe and then decompile
> > again with bmf2mof?  As long as it's coming out the same you're
> > probably right.
> 
> Yes, bmf2mof+mofcomp.exe+bmf2mof gives same output as just bmf2mof.

I changed order for printing qualifiers in bmf2mof. "in" and "out" are 
now printed before all others. So you should see now same output.

> > > > > > > source:
> > > > > > > 	void DoBFn([in, out, Description("Fn buf")] BDat Data);
> > > > > > > 
> > > > > > > bmf2mof:
> > > > > > > 	void doBFn([in, Description("Fn buf"), ID(0)] BDat
> > > > > > > 	Data,
> > > > > > > 	[out, Description("Fn buf"), ID(0)] BDat Data);
> > > > > 
> > > > > --
> > > > > Pali Rohár
> > > > > pali.rohar@gmail.com
> > > 
> > > --
> > > Pali Rohár
> > > pali.rohar@gmail.com
diff mbox

Patch

diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 49a1d01..1f27600 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -656,6 +656,18 @@  config ACPI_WMI
 	  It is safe to enable this driver even if your DSDT doesn't define
 	  any ACPI-WMI devices.
 
+config WMI_MOF
+	tristate "WMI embedded MOF driver"
+	depends on ACPI_WMI
+	default y
+	---help---
+	  Say Y here if you want to be able to read a firmware-embedded
+	  WMI MOF schema.  Using this requires userspace tools and may be
+	  rather tedious.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called wmi-mof.
+
 config MSI_WMI
 	tristate "MSI WMI extras"
 	depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 652d7c8..1147212 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -38,6 +38,7 @@  obj-$(CONFIG_MSI_WMI)		+= msi-wmi.o
 obj-$(CONFIG_PEAQ_WMI)		+= peaq-wmi.o
 obj-$(CONFIG_SURFACE3_WMI)	+= surface3-wmi.o
 obj-$(CONFIG_TOPSTAR_LAPTOP)	+= topstar-laptop.o
+obj-$(CONFIG_WMI_MOF)		+= wmi-mof.o
 
 # toshiba_acpi must link after wmi to ensure that wmi devices are found
 # before toshiba_acpi initializes
diff --git a/drivers/platform/x86/wmi-mof.c b/drivers/platform/x86/wmi-mof.c
new file mode 100644
index 0000000..464ceca
--- /dev/null
+++ b/drivers/platform/x86/wmi-mof.c
@@ -0,0 +1,125 @@ 
+/*
+ * WMI embedded MOF driver
+ *
+ * Copyright (c) 2015 Andrew Lutomirski
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/acpi.h>
+#include <linux/string.h>
+#include <linux/dmi.h>
+#include <linux/wmi.h>
+#include <acpi/video.h>
+
+#define WMI_MOF_GUID "05901221-D566-11D1-B2F0-00A0C9062910"
+MODULE_ALIAS("wmi:" WMI_MOF_GUID);
+
+struct mof_priv {
+	union acpi_object *mofdata;
+	struct bin_attribute mof_bin_attr;
+};
+
+static ssize_t
+read_mof(struct file *filp, struct kobject *kobj,
+	 struct bin_attribute *attr,
+	 char *buf, loff_t off, size_t count)
+{
+	struct mof_priv *priv =
+		container_of(attr, struct mof_priv, mof_bin_attr);
+
+	if (off >= priv->mofdata->buffer.length)
+		return 0;
+
+	if (count > priv->mofdata->buffer.length - off)
+		count = priv->mofdata->buffer.length - off;
+
+	memcpy(buf, priv->mofdata->buffer.pointer + off, count);
+	return count;
+}
+
+static int wmi_mof_probe(struct wmi_device *wdev)
+{
+	int ret;
+
+	struct mof_priv *priv =
+		devm_kzalloc(&wdev->dev, sizeof(struct mof_priv), GFP_KERNEL);
+
+	if (!priv)
+		return -ENOMEM;
+
+	dev_set_drvdata(&wdev->dev, priv);
+
+	priv->mofdata = wmidev_block_query(wdev, 0);
+	if (!priv->mofdata) {
+		dev_warn(&wdev->dev, "failed to read MOF\n");
+		return -EIO;
+	}
+
+	if (priv->mofdata->type != ACPI_TYPE_BUFFER) {
+		dev_warn(&wdev->dev, "MOF is not a buffer\n");
+		ret = -EIO;
+		goto err_free;
+	}
+
+	sysfs_bin_attr_init(&priv->mof_bin_attr);
+	priv->mof_bin_attr.attr.name = "mof";
+	priv->mof_bin_attr.attr.mode = 0400;
+	priv->mof_bin_attr.read = read_mof;
+	priv->mof_bin_attr.size = priv->mofdata->buffer.length;
+
+	ret = sysfs_create_bin_file(&wdev->dev.kobj, &priv->mof_bin_attr);
+	if (ret)
+		goto err_free;
+
+	return 0;
+
+err_free:
+	kfree(priv->mofdata);
+	return ret;
+}
+
+static int wmi_mof_remove(struct wmi_device *wdev)
+{
+	struct mof_priv *priv = dev_get_drvdata(&wdev->dev);
+
+	sysfs_remove_bin_file(&wdev->dev.kobj, &priv->mof_bin_attr);
+	kfree(priv->mofdata);
+	return 0;
+}
+
+static const struct wmi_device_id wmi_mof_id_table[] = {
+	{ .guid_string = WMI_MOF_GUID },
+	{ },
+};
+
+static struct wmi_driver wmi_mof_driver = {
+	.driver = {
+		.name = "wmi-mof",
+	},
+	.probe = wmi_mof_probe,
+	.remove = wmi_mof_remove,
+	.id_table = wmi_mof_id_table,
+};
+
+module_wmi_driver(wmi_mof_driver);
+
+MODULE_AUTHOR("Andrew Lutomirski <luto@kernel.org>");
+MODULE_DESCRIPTION("WMI embedded MOF driver");
+MODULE_LICENSE("GPL");