ACPI WMI雑記

14326 ワード

WMI ACPIについては、まず通読することをお勧めします:1.WMI ACPIが何を提供できるかを知ってから、MSDN 2を参照してください.また、3.1としてもよい.と入力します.特に説明する必要がある.中にはdemoプログラムが残っていて、一般の読者は環境テストがありません(実際の機械でテストすることもお勧めしません.万が一電源を入れないと損失が大きい場合)、私の文章を参考にして、既存のBIOSからMOFとWMIインタフェースを抽出して勉強に使うことができます.
本文は1文の原理の補充と総括であるべきで、主にMOF資源ファイルとACPIの中の各WMIインタフェースの関係を補充します.彼らの関係を明らかにするには、まず文で使用されているコードシートを使用します.
Mof記述ファイル:
// Author: bini.Yi  http://www.ufoit.com 2008-09-24
// File: demowmi.mof
//{39142400-C6A3-40fa-BADB-8A2652834100}
//IMPLEMENT_OLECREATE
//0x39142400, 0xc6a3, 0x40fa, 0xba, 0xdb, 0x8a, 0x26, 0x52, 0x83, 0x41, 0x00);

[WMI,
Dynamic,
Provider("WmiProv"),
Locale("MS\\0x409"),
Description("Events"),
guid("{39142400-C6A3-40fa-BADB-8A2652834100}")
]
class DemoWMIData
{
    [key, read]
     string InstanceName;
    [read] boolean Active;

    [WmiDataId(1),
     read, write,
     Description("description")
    ] uint32 Data;
};

ASL(WMI)ファイル:
// Author: bini.Yi  2008-09-24
// File: demowmi.ASL

Device(DWMI)
{
	// PNP0C14 is PNP ID assigned to WMI mapper
	Name(_HID, EISAID("PNP0C14"))
	Name(_UID, 0x0)

	Name(_WDG, Buffer(){
        // {39142400-C6A3-40fa-BADB-8A2652834100}
        0x00, 0x24, 0x14, 0x39, 0xA3, 0xC6, 0xFA, 0x40, 
        0xBA, 0xDB, 0x8A, 0x26, 0x52, 0x83, 0x41, 0x00, //GUID
        0x30, 0x30, //'00' Object ID
        0x01, //Instance Num
        0x01,		// 00 = Demo
	})

	Name(DD00, 0)

	Method(WQ00, 1)
	{
	  DBGS("Demo Wmi Get Function:")
	  DW2H(DD00)
		Return(DD00)
	}

	Method(WS00, 2)
	{
	  DBGS("Demo Wmi Set Function:")
	  DW2H(ARG1)
		Store(ARG1, DD00)
	}
}

WMI ACPI呼び出しモデル:


MOF記述ファイルは最終的にユーザに呼び出されたインタフェースであり、WMI ACPIのASL code部分はMOFに記述されたClassの実装である.読者がMOF/ALLファイルを繰り返し読んで比較すると、ダイナミックリンクライブラリに似ていると感じます.MOFファイルはClassヘッダファイルのように、呼び出しインタフェースの約束とエクスポートを担当します.ASLはDLLファイルのようにDLL関数の実装を担当する.に至ってはWDGオブジェクトは、DLLのEAT(関数アドレステーブル)の仲介役として機能します(実際には_WDGオブジェクトに埋め込まれたMOFファイルにも依存しますが、後述します).もちろんEATテーブルにはいくつかのテーブル項目が構成されている可能性があります.WDGオブジェクトもそうです._WDGの単一のテーブル・アイテムには、次のデータ構造があります.
typedef struct _Mapper
{
     GUID guid;             // GUID that names data block
     union
     {
         CHAR ObjectId[2];  // 2-character ACPI ID  (Data Blocks and Methods)
         struct 
         {
             UCHAR NotificationValue;  // Byte value passed by event handler control method
             UCHAR Reserved[1];
         } NotifyId;
    }
     USHORT InstanceCount;  // Number of separate instances of data block
     USHORT Flags;          // Flags
}Mapper;

すべてのテーブルアイテムが結合すると、巨大なMapper[N]配列が形成され、この配列は最終的に_WDGオブジェクト.Mofリソースファイルの作成者(間違いなくOEMメーカー)は、_WDGオブジェクトごとにMapper[i]ごとにClassを作成します.クラスごとにMapper[i]があります.guid対応.

呼び出しプロセス(個人的な憶測ですが、理にかなっていると思います!):

  • WMIの呼び出し者(DLLと想像する呼び出し者)は、MOFリソースファイル(Classヘッダファイルと想像する)で記述するWMIインタフェースに従って、ClassNameの形式でASL codeの(DLLファイルと想像する)を呼び出すとき、ACPI.SysはACPIネーミングスペースで先に検索します.WDGオブジェクト.
  • 見つかった_WDGオブジェクトの後、そのMapper[N]配列を遍歴し、Mapper[i]に位置決めする.Flags=0の配列項目.この配列項目は、コンパイルされたMOFファイルを含むbufferを指し、MSDNは埋め込み型MOFリソースと呼ばれています.
  • ACPI.Sysは、上位レイヤがClassを使用してWMIを呼び出すため、埋め込み型Mofリソースから一致するClassNameを検索します.前のMofリソース記述ファイルにguidとClassNameが含まれていることを思い出してみてください.
  • ClassNameを取得すると、さらにインタフェース名のguidを取得して_に戻ることができます.WDGのMapper[N]配列では、Mapper[i]による.guidは呼び出し元GUIDに一致する配列項目を検索する.
  • がGUIDにマッチする後、ACPI.SysはMapper[i]を取り出す.ObjectIDメンバー、メンバーにxx値、ACPIを含む.SysはWQ/WSとxxをつなぎ合わせてWQxxまたはWSxxを形成し、ACPIネーミングスペースに行って対応するWQxxまたはWSxxメソッドを呼び出す.demoプログラムとして、WDGオブジェクトのMapper[N]配列は1つの配列項のみであり,上記探索過程は反映されていない.だから、N>1の例を変えて、うーん、抽出したThinkPadの_WDGオブジェクト:
  •         Device (WMI2)
            {
                Name (_HID, EisaId ("PNP0C14") /* Windows Management Instrumentation Device */)  // _HID: Hardware ID
                Name (_UID, 0x02)  // _UID: Unique ID
                Name (_WDG, Buffer (0x64)
                {
                //==============Mapper[0]==============
                                0xF1, 0x24, 0xB4, 0xFC, 0x5A, 0x07, 0x0E, 0x4E,
                                0xBF, 0xC4, 0x62, 0xF3, 0xE7, 0x17, 0x71, 0xFA,
                                0x41, 0x37,
                                0x01,
                                0x01,
                 //==============Mapper[1]==============
                                0xE3, 0x5E, 0xBE, 0xE2, 0xDA, 0x42, 0xDB, 0x49, 
                                0x83, 0x78, 0x1F, 0x52, 0x47, 0x38, 0x82, 0x02,
                                0x41, 0x38,
                                0x01,
                                0x02,
                 //==============Mapper[2]==============
                                0x9A, 0x01, 0x30, 0x74, 0xE9, 0xDC, 0x48, 0x45,
                                0xBA, 0xB0, 0x9F, 0xDE, 0x09, 0x35, 0xCA, 0xFF, 
                                0x41, 0x39,
                                0x0A,
                                0x05,
                 //==============Mapper[3]==============
                                0x03, 0x70, 0xF4, 0x7F, 0x6C, 0x3B, 0x5E, 0x4E,
                                0xA2, 0x27, 0xE9, 0x79, 0x82, 0x4A, 0x85, 0xD1,
                                0x41, 0x41,
                                0x01,
                                0x06,
                 //==============Mapper[4]==============
                                0x21, 0x12, 0x90, 0x05, 0x66, 0xD5, 0xD1, 0x11,
                                0xB2, 0xF0, 0x00, 0xA0, 0xC9, 0x06, 0x29, 0x10, 
                                0x42, 0x42,
                                0x01,
                                0x00                           
                })

    ThinkPad T 460部ですWDGオブジェクトは、5つの配列項目があり、最後に特殊な配列項目であり、しばらく議論しない.他のいくつかの配列項目に対応するWMIインタフェースは以下の通りである.
    On Error Resume Next
     
    Set fso = CreateObject("Scripting.FileSystemObject")
    Set a = fso.CreateTextFile("lenvon.log", True)
    Set Service = GetObject("winmgmts:{impersonationLevel=impersonate}!root/wmi")
    Rem Lenovo_PreloadLanguage - Preload Language
    Set enumSet = Service.InstancesOf ("Lenovo_PreloadLanguage")
    a.WriteLine("Lenovo_PreloadLanguage")
    for each instance in enumSet
        a.WriteLine("    InstanceName=" & instance.InstanceName)
        a.WriteLine("        instance.CurrentSetting=" & instance.CurrentSetting)
    next 'instance
    Rem Lenovo_SetPreloadLanguage - Set Preload Language
    Set enumSet = Service.InstancesOf ("Lenovo_SetPreloadLanguage")
    a.WriteLine("Lenovo_SetPreloadLanguage")
    for each instance in enumSet
        a.WriteLine("    InstanceName=" & instance.InstanceName)
    next 'instance
     
    Rem Lenovo_PlatformSetting - Platform Setting
    Set enumSet = Service.InstancesOf ("Lenovo_PlatformSetting")
    a.WriteLine("Lenovo_PlatformSetting")
    for each instance in enumSet
        a.WriteLine("    InstanceName=" & instance.InstanceName)
        a.WriteLine("        instance.CurrentSetting=" & instance.CurrentSetting)
    next 'instance
    Rem Lenovo_SetPlatformSetting - Set Platform Setting
    Set enumSet = Service.InstancesOf ("Lenovo_SetPlatformSetting")
    a.WriteLine("Lenovo_SetPlatformSetting")
    for each instance in enumSet
        a.WriteLine("    InstanceName=" & instance.InstanceName)
    next 'instance
     
    a.Close
    Wscript.Echo "lenvon Test Completed, see lenvon.log for details"

    ThinkPadは埋め込みMOFを使用しているため、元のMofファイル(demowmi.mofのように)を取得できませんが、このvbsスクリプトを実行すると、mofの可能性のある内容を推測できます.
    //entry 1
    [WMI,
    Dynamic,
    Provider("WmiProv"),
    Locale("MS\\0x409"),
    Description("Platform Setting"),
    guid("{0x9A, 0x01, 0x30, 0x74, 0xE9, 0xDC, 0x48, 0x45,
          0xBA, 0xB0, 0x9F, 0xDE, 0x09, 0x35, 0xCA, 0xFF}")
    ]
    class Lenovo_PlatformSetting
    {
        [key, read]
         string InstanceName;
        [read] boolean Active;
    
        [WmiDataId(0x0A),
         read, write,
         Description("platfrom setting")
        ] String CurrentSetting;
    };
    
    //entry 2
    [WMI,
    Dynamic,
    Provider("WmiProv"),
    Locale("MS\\0x409"),
    Description("Platform Setting"),
    guid("{0x03, 0x70, 0xF4, 0x7F, 0x6C, 0x3B, 0x5E, 0x4E,
         0xA2, 0x27, 0xE9, 0x79, 0x82, 0x4A, 0x85, 0xD1}")
    ]
    class Lenovo_SetPlatformSetting
    {
        [key, read]
         string InstanceName;
        [read] boolean Active;
        
        [WmiMethodId,
        Description("Set platfrom setting")
        ]
    }
    
    //entry 3
    [WMI,
    Dynamic,
    Provider("WmiProv"),
    Locale("MS\\0x409"),
    Description("Platform Setting"),
    guid("{0xF1, 0x24, 0xB4, 0xFC, 0x5A, 0x07, 0x0E, 0x4E,
           0xBF, 0xC4, 0x62, 0xF3, 0xE7, 0x17, 0x71, 0xFA}")
    ]
    class Lenovo_PreloadLanguage
    {
        [key, read]
         string InstanceName;
        [read] boolean Active;
    
        [WmiDataId(0x01),
         read, write,
         Description("Preload Langugage")
        ] String CurrentSetting;
    }
    
    //entry 4
    [WMI,
    Dynamic,
    Provider("WmiProv"),
    Locale("MS\\0x409"),
    Description("Platform Setting"),
    guid("{}")
    ]
    class Lenovo_SetPreloadLanguage
    {
        [key, read]
         string InstanceName;
        [read] boolean Active;
    
        [WmiMethodId,
        Description("Set Set Preload Language")
        ]
    }

    VBSのInstanceOf:


    Wmi Code generateによって生成されたACPI WMIインタフェースのテストスクリプトには、多くのInstanceOfinstance文があります.
    Set enumSet = Service.InstancesOf ("Lenovo_PlatformSetting")
    a.WriteLine("Lenovo_PlatformSetting")
    for each instance in enumSet
        a.WriteLine("    InstanceName=" & instance.InstanceName)
        a.WriteLine("        instance.CurrentSetting=" & instance.CurrentSetting)
    next 'instance

    (以下は個人的に理解する:)Mofリソースファイルは_WDGオブジェクトの配列項目ごとにClassを編集します.オブジェクト指向思考を適用するには、メンバーにアクセスするにはクラスオブジェクト(インスタンス化Class)を作成する必要があるため、vbsスクリプトでは
    Set enumSet = Service.InstancesOf ("Lenovo_PlatformSetting")

    Mofリソースファイルで説明されているLenovo_を作成する必要があります.PlatformSettingsクラスオブジェクトで、enumSetと名付けられます.

    VBSの「for each instance in enumSet」:


    enumSetをクラスのオブジェクトとして理解すると、vbsスクリプトのinstanceは、Mofリソースファイルに記述されているクラスの各メンバー変数です.注意すべきは、vbsテストスクリプトを読むと、クラスオブジェクトの各メンバーにループしてアクセスしていることがわかります.したがって、クラスオブジェクトのメンバー変数のタイプが一致しているため、配列を構成することができます.また、特殊な場合、配列に1つしかない場合、配列は通常の変数に簡略化されます.のためにWDGオブジェクトにおけるMapper[N]配列区分は,Classにおけるタイプが一致するメンバー変数をItem配列で表す.Item配列の長さ(すなわちinstanceの数またはforループの回数)は_WDGオブジェクトのMapper[i].instanceCountでは、次のように指定されています.
    // !
    typedef struct _Mapper
    {
         GUID guid;             // GUID that names data block
         union
         {
             CHAR ObjectId[2];  // 2-character ACPI ID  (Data Blocks and Methods)
             struct 
             {
                 UCHAR NotificationValue;  // Byte value passed by event handler control method
                 UCHAR Reserved[1];
             } NotifyId;
        }
         USHORT InstanceCount;  // 

    ThinkPad T 460 Pを例にとると、
    Class:Lenovo_PlatformSetting.InstanceCount=0x0A;
    Class:Lenovo_SetPlarformSeting.InstanceCount=0x01;
    これらはすべて_WDGオブジェクトMapper[i].InstanceCountで手がかりを見つけた:
            Device (WMI2)
            {
                Name (_HID, EisaId ("PNP0C14") /* Windows Management Instrumentation Device */)  // _HID: Hardware ID
                Name (_UID, 0x02)  // _UID: Unique ID
                Name (_WDG, Buffer (0x64)
                {
    ...
                 //==============Mapper[2]==============
                                0x9A, 0x01, 0x30, 0x74, 0xE9, 0xDC, 0x48, 0x45,
                                0xBA, 0xB0, 0x9F, 0xDE, 0x09, 0x35, 0xCA, 0xFF, 
                                0x41, 0x39,
                                0x0A, 

    ただし、Item配列の長さはMapper[i]に従う.InstanceCountの値は固定できますが、Item配列の配列項目タイプは指定されていません.簡単なのはUINTタイプのItem配列かもしれませんが、複雑なのはBufferまたはPackageタイプのItemかもしれません(ここではItem配列を使用しています).ThinkPad T 460 P Lenovo_PlarformSetingクラスを例にとると、Lenovo_PlarformSetingクラス関数はLenovo_PlarformSetingは、WMI ACPIでの実装:Method(WQA 9,1,NotSerialized)
    Method (WQA9, 1, NotSerialized)
    {
        Acquire (\_SB.WMI1.MWMI, 0xFFFF)
        If ((\WMIS (0x09, Arg0) != 0x00))
        {
            Release (\_SB.WMI1.MWMI)
            Return ("")
        }
    
        Local0 = DerefOf (ITEM [\WITM])
        Local1 = DerefOf (Local0 [0x00])
        Local2 = DerefOf (Local0 [0x01])
        Concatenate (Local2, ",", Local6)
        Local3 = DerefOf (VSEL [Local1])
        Concatenate (Local6, DerefOf (Local3 [\WSEL]), Local7)
        Release (\_SB.WMI1.MWMI)
        Return (Local7)
    }

    Method WQA 9は、一意のパラメータArg 0に基づいてACPIネーミングスペースITEMオブジェクトから数値を取得する.ITEMオブジェクトについては、このように長いです.
    Name (ITEM, Package (0x06)
    {
        Package (0x02)
        {
            0x00, 
            "InhibitEnteringThinkPadSetup"
        }, 
    
        Package (0x02)
        {
            0x00, 
            "MTMSerialConcatenation"
        }, 
    
        Package (0x02)
        {
            0x00, 
            "SwapProductName"
        }, 
    
        Package (0x02)
        {
            0x00, 
            "ComputraceMsgDisable"
        }, 
    
        Package (0x02)
        {
            0x00, 
            "CpuDebugEnable"
        }, 
    
        Package (0x02)
        {
            0x00, 
            "PasswordAfterBootDeviceList"
        }
    })

    ええと、この構造はちょっと複雑で、読めません.次のように整理します.
    1.ACPI構文によれば、Packageは構造体と考えてもよいし、配列と考えてもよい.最内層のPackage(0 x 2)を2つのメンバ変数のみの構造体とする.
    typedef struct _SettingEntry
    {
        UINT32 SettingVal;
        char*  SettingName;
    }SettingEntry;

    外層Packageは当然、このような構造体タイプのItem配列と考えられており、配列項目は計6項目(_WDGはその配列項目が10項目であるべきことを指定しているが、実際には6項目しかなく、アクセスオーバー部分にも異常は発生していない!):
    SettingEntry T460P[] = {{0x00,"InhibitEnteringThinkPadSetup"},
                             {0x00,"MTMSerialConcatenation"},
                             {0x00,"SwapProductName"},
                             {0x00,"ComputraceMsgDisable"},
                             {0x00,"CpuDebugEnable"},
                             {0x00,"PasswordAfterBootDeviceList"}
                             };

    私たちのタイトルに戻ります:VBSの中の“for each instance in enumSet”、vbsは1ラウンドごとに循環して、実はT 460 P[n]にアクセスします.T 460 P[n]のみにアクセスするなど、OEMメーカーによっては複雑なアクセスを行う場合がある.SettingValまたはT 460 P[n]である.SettingName.このとき,ASLコードに大量のDerefOf文が見られる.

    _WDGの特殊なFlag:


    各_WDGオブジェクトMapper[N]配列には、0 x 00の特殊なFlags値を持つ(一意の)特殊な配列項目があります.この特殊なMapper[i]配列項目は1つの役割しかありません:bufferを提供し、コンパイルされたMofリソースファイルを格納するので、このテーブル項目自体はMofリソース記述ファイルには表示されません.しかし、ACPI WMIインタフェースの呼び出しを構成する上で重要なステップであり、それがなければ、Class名からACPI Methodへの変換は実現できません.