piątek, grudnia 16, 2011

MOF decompilation

Background

So, you have read very nice article about writing new WMI drivers for kernel, you have downloaded and read how to start manual, you have even read very interesting kernel WMI reference on Ubuntu site. And you are so buzzed with good feelings about this all that you push some commands to dump WMI information from DSDT. Then in completely unexpected way you have to face with...

Reality

    97845ED0-4E6D-11DE-8A39-0800200C9A66:
        object_id: BC
        notify_id: 42
        reserved: 43
        instance_count: 1
        flags: 0x2 ACPI_WMI_METHOD 
    466747A0-70EC-11DE-8A39-0800200C9A66:
        object_id: BD
        notify_id: 42
        reserved: 44
        instance_count: 1
        flags: 0x2 ACPI_WMI_METHOD 
    ABBC0F72-8EA1-11D1-00A0-C90629100000:
        object_id: ?
        notify_id: D2
        reserved: 00
        instance_count: 1
        flags: 0x8 ACPI_WMI_EVENT 
    05901221-D566-11D1-B2F0-00A0C9062910:
        object_id: MO
        notify_id: 4D
        reserved: 4F
        instance_count: 1
        flags: 0

What the heck? It is clearly written what is a function, what is and event and what is something else, articles authors tell you about structures from their computers, but they does not tell a word about your machine. There is no function or parameter description, just "there is a GUID, do what you want with that". You are half lucky if you connect to events and are able to collect some data in the field, but when your machine (like mine) require to send some greetings in advance to receive them, then you are in big troubles. There are two ways of dealing with this...

Ninja

Dig through DSDT, observe function calls flow, chop-out parameters and their type, guess, try and guess again. Then, you should sit near the fireplace and tell all of this to your grandchildrens. There is a chance to get crazy in the process, but you are dealing with "The Kernel", you were warned before you have started. To take away risk, I have for you...

Solution


There is a tool in the Windows Driver Development kit, called wmiofck. Which is designed to check mbf (compiled mof file), and to create interface definitions for it. Most of the WMI based DSDT have in them something called WQXX buffers, they are nothing more than compiled mof files. Just dig them out, and save as a binary file (not so complicated if you know some of the script-fu). Call wmiofck tool on this binary file with parameters:

wmiofck.exe -hwmidevs.h -m -u moftable.mbf
in result you will receive very nicely formatted C .h file, where all WMI functions will have the same names as your device manufacturer wanted them to have. Some of them will have comments, all your parameters will be fully described. Sometimes even some constants will be exposed. You don't belive me? See for yourself:

// ASUSManagement - ASUSManagement #define ASUSManagementGuid \ { 0x97845ed0,0x4e6d,0x11de, { 0x8a,0x39,0x08,0x00,0x20,0x0c,0x9a,0x66 } } #if ! (defined(MIDL_PASS)) DEFINE_GUID(ASUSManagement_GUID, \ 0x97845ed0,0x4e6d,0x11de,0x8a,0x39,0x08,0x00,0x20,0x0c,0x9a,0x66); #endif // // Method id definitions for ASUSManagement #define initialize 1128616019 typedef struct _initialize_IN { // ULONG AP_version; #define initialize_IN_AP_version_SIZE sizeof(ULONG) #define initialize_IN_AP_version_ID 1 } initialize_IN, *Pinitialize_IN; #define initialize_IN_SIZE (FIELD_OFFSET(initialize_IN, AP_version) + initialize_IN_AP_version_SIZE) typedef struct _initialize_OUT { // ULONG BIOS_version; #define initialize_OUT_BIOS_version_SIZE sizeof(ULONG) #define initialize_OUT_BIOS_version_ID 2 } initialize_OUT, *Pinitialize_OUT; #define initialize_OUT_SIZE (FIELD_OFFSET(initialize_OUT, BIOS_version) + initialize_OUT_BIOS_version_SIZE)
This is decompiled version of MOF file from the article mentioned in the beginning of this post, first GUID definition is the GUID for a endpoint called ASUSManagement, then you have method id and input/output parameter descriptions. If you are lucky, and your machine manufacturer was not lazy you will have full API for your machine. Served as you like, chilled with some #define on top.

Full version of generated .h file can be grabbed here. It is very good lecture, especially when used as a reference for initial how to.