The Common
Diagnostic Model (CDM) is a framework for publishing device diagnostics and
their results. Since it is based upon CIM it is closely coupled with other CIM
classes and is part of the CIM heirarchy. However this would require that any
kernel mode device driver that wants to expose diagnostics via CDM to not only
implement the diagnostics in the device driver, but also write a WMI user mode
provider that can interface with CIM. Having to also write the WMI user mode
provider would be a disincentive to driver writers to include diagnostics. This
paper proposes writingdescribes a
generic WMI user mode provider (CDMProv) that would bridge the gap between CDM
and the kernel mode device driver. Device driver writers could implement
diagnostics within their kernel device driver and the CDM provider would
publish the tests and results on behalf of the device driver.
Since device drivers run in kernel mode they cannot interface with the DCOM interfaces provided by WMI and thus cannot be a traditional WMI provider. Drivers have no access to the WMI schema and due to the spartan nature of device driver design, drivers must expose their instrumentation data in a very simple way. Device drivers define data blocks which are named by a unique guid. Each data block may contain one or more data items. There may be more than one instance of the data block for a particular device and multiple devices may support the same data block so each instance of a data block is assigned an instance name which is typically a permutaion on the device’s PnP device id.
So each data block is roughly equivalent to a WMI class and each data item within the class is roughly equivalent to a WMI property within the class. Because the interface to the device driver expects that the data block is formatted in a particular way a number of WDM specific qualifiers were invented that describe the order of the class properties within the data block, the guid that associates the driver data block to the class, and how to interpert variable length arrays. The device driver supplies the MOF as a blob of data and does no interpertation of it.
In order to allow access to the device driver’s data blocks by WMI consumers a WMI user mode provider named Wmiprov was written. This provider will access the device driver’s data blocks via the classes and WDM specific qualifiers specified in the driver’s MOF. However this provider is rather limited in functionality and cannot express associations, object references and does not try to associate the PnP ids specified in the data blocks with the PnP ids as stored within CIM classes such as CIM_LogicalDevice.
Since CDM relies upon CIM and always associates diagnostics tests with a CIM_ManagedSystemElement and Wmiprov can only supply a PnP Id for a WDM data block, some sort of mapping is needed so that diagnostics exposed by the driver as WDM data blocks can be exposed by CDM within the CIM framework. Typically there is an instance of a class derived from CIM_LogicalDevice would be related to the device that supplies WDM data blocks. Since a class derived from CIM_LogicalDevice is also derived from CIM_ManagedSystemElement instances of that class could be used wherever the CDM framework requires a CIM_ManagedSystemElement class instance. Additionally CIM_LogicalDevice contains a PnPDeviceId property whose value is the PnP Id associated with the device. Thus it should be possible to do a mapping between WDM data blocks and instances of classes derived from CIM_LogicalDevice.
One issue that needs further
investigation is how to deal with a situation where there is not a 1 to 1
mapping between PnP Id and CIM_LogicalDevice derived class instance.In order to implement the
mapping between CIM and WDM classes it is required that the device driver use
PDO or PnP Device Id based instance names when registering its data blocks. It is also required that a
name of a CIM_LogicalDevice derived class be supplied so that the CIM class
instance can be found.
A situation where there is more than one device that has the same PnP Id would not be an issue as this would only occur in the situation where more than one device object in the device stack is supplying WDM data blocks. Typically all of the devices objects in a stack are supplying information about the same physical (or logical) device so mapping them all to the same CIM_LogicalDevice derived class instance would not be problematic.
The Another situation that may
occur is when a PnP Id would map to more than one CIM_LogicalDevice derived
class instance. Typically this would be for a multifunction device, for example
a CD/DVD drive that might map to a an instance of a DVD class and an
instance of a CD class. Depending
upon the CIM mapping class chosen the diagnostic could apply to both the CD and
DVD CIM class
instance or apply
to only one of them
whichever is appropriate. In this case the diagnostic test would be made
available for both the CD and DVD class instances. This would most likely be
correct in that the diagnostic test would apply to both devices. If this were
not the case, for example there is a DVD specific test which should not apply
to the CD class, more information is needed from the device driver. This is
done by allowing the device driver to include a special qualifier on the
diagnostic test class which would specify which set of CIM_LogicalDevice
derived classes to search for the matching PnP Id. In fact this special
qualifier should be used whenever possible since it improves the accuracy and
performance of the mapping.
Wmiprov has strict rules for how the classes that represent the WDM data blocks must be composed and is limited in the WMI functionality that it can expose to the device driver. Additionally Wmiprov does not do the CIM_LogicalDevice to PnP Id mapping described above. Therefore it is not possible to directly take a CDM derived class and expect Wmiprov to be able to implement it. There is an intermediate layer that implements the CDM classes and interfaces with the device driver via the WDM provider. This layer is the generic CDM provider or CDMProv.
The device
driver writes MOF for both
the CDM classes which specify those classes that the classes are
implemented by the CDM provider and the WDM classes which specify those classes
that are implemented by the device driver to support the implementation of the
CDM classes.. The CDM
classes and properties will also include
special CDM provider specific qualifers that inform the CDM provider how to
implement the CDM classes and which WDM classes shadow them. The [AW1]CDM provider uses the
information in the CDM classes to dynamically generate a set of WDM classes that shadow the CDM classes and can be used with
the WDM provider to interface with the device driver[AW2]. Alternatively the driver
writer can write MOF for the shadow classes if it requires more control over the
mapping of CDM class to WDM class or allow the WmiMofCk tool to generate WDM
classes. The device driver implements the data blocks represented
by the shadow WDM classes
.
These shadow WDM classes can beand are handled directly by Wmiprov as any
other WDM class would be.
So whenever a CDM class is invoked the CDM provider will reflect the operation
to the WDM class and via the WDM provider a request is made of the device
driver implementing those classes.
The CDM
provider will create and maintain all of the CDM specific class instances and
associations. It can dodoes this either when the CDM provider
loads and when new devices drivers appear or it can do it on
demand,
ie;
whenever the
particular class or association is accessed the CDM provider will obtain all information
needed to complete the operation. The CDM provider will invoke the WDM
classes only when it needs to interact with the device driver. [More on
how it works]
The shadow classes
for all CIM_DiagnosticTest, CIM_DiagnosticSetting and CIM_DiagnosticResults
derived classes are in turn derived frombased upon the idealized WDM
classes WDM_DiagnosticTest, WDM_DiagnosticSettings and WDM_DiagnosticResults.
WDM_DiagnosticTest. The actual driver WDM classes are not derived from these classes, but
are modeled from them. This is because each class must be able to
define unique values within a ValueMap and it is not possible to extend a ValueMap that
is specified in a base class.
Additional properties may be specified in the CDM class and in the shadow class. The CDM provider maps these properties between the CDM and WDM shadow classes, but only maps those properties if the names and data types are identical. The only exception to this is that the CDM provider will map enumerations (ValueMaps) from the WDM shadow classes into strings in the CDM classes.
WDM
Diagnostic Test class
The WDM _Diagnostic Test class is
the base WDM class that returns information
about the specific diagnostic test and has methods that can run or discontinue
the specific test. The CDM provider assigns the shadow class derived
frombased
upon WDM _Diagnostic Test to the
corresponding CDM CIM_DiagnosticTest derived classes. The CDM provider uses the
shadow class when the corresponding CIM_DiagnosticTest class is invoked. Any
additional properties and methods specified in the
CIM_DiagnosticTest derived class are reflected in the
shadow class. The driver implements the data block and methods in
the driver to return the test information and execute the methods as specified
by the shadow class.
The
WDM Diagnostic Test class includes a RunTest method that has a single input parameter
and a single output parameter, both of which are embedded classes. The class names of the
parameter
embedded classes can be arbitrary, however the property names and types of those classes are
not. The input embedded class has two parameters: a string named ExecutionID
and an embedded WDM Diagnostic Setting class named DiagSettings. The output
embedded class has a uint32 value named Result and an embedded WDM
Diagnostic Result class named DiagResult.
WDM _Diagnostic Settings class
The WDM _Diagnostic Settings class
is an embedded class that is an input parameter to the WDM _Diagnostic Test RunTest
method. It specifies all of the settings to use when executing the test. An array of these embedded classes is also
returned when
the WDM Diagnostic Settings List class is queried. Classes derived from
WDM_DiagnosticSettings may be specified in as the
shadow class and used by the CDM provider if the CDM classes utilize classes
derived from the CIM_DiagnosticSettings class. Additional properties
may be specified in the CDM and WDM classes provided the property names and
types are identical.
WDM _Diagnostic Settings List class
The
WDM _Diagnostic Settings List class is implemented by
the device driver and returns an array of WDM _Diagnostic Settings embedded classes. Each embedded class is a
WDM_DiagnosticSettings embedded classinstance that specifies the possible settings that
can be used by the consumer to execute the test.
WDM _Diagnostic Results class
The WDM _Diagnostic Results class is
an embedded class that is an output from the WDM _Diagnostic Test RunTest
method. It contains all of the results returned by the driver after the test
has been completed. Classes derived from WDM_DiagnosticResults may be
specified in as the shadow class and
used by the CDM provider if the CDM classes utilize classes derived from the
CIM_DiagnosticResults class.Additional properties may be specified in the WDM
and CDM classes provided the property names and types are identical or the WDM
property is a valuemap and the CDM property is a string.
Here is the MOF that
describes these three classes
[abstract,
WMI
]
class
WDM_DiagnosticTest
{
//
//
Properties
//
[Description(
"If this test is currently being
performed, the InUse "
"property is set to
TRUE."),
read,
WmiDataId(1)
]
boolean IsInUse = FALSE;
[
WmiDataId(2),
read
]
uint32 ResourcesUsedCount;
[
Description(
"The \"Expensive\" qualifier can be applied to this class
and "
"its RunTest method. If so, the
ResourcesUsed property "
"describes the resources that
are capitalized, based on a "
"default setup for the test.
Multiple resources can be "
"specified since the property is an array."),
read,
ValueMap{"CPU",
"Memory", "Hard Disk", "CDROM",
"Floppy",
"PCI Bus", "USB
Bus", "1394 Bus", "SCSI Bus", "IDE Bus",
"Network", "ISA
Bus", "EISA Bus", "VESA Bus", "PCMCIA Bus",
"CardBus",
"Access.bus", "NuBus", "AGP", "VME
Bus",
"Sbus IEEE 1396-1993",
"MCA Bus", "GIO Bus", "XIO Bus",
"HIO Bus", "PMC
Bus", "SIO Bus"},
WmiSizeIs("ResourcesUsedCount"),
WmiDataId(3)
]
uint16 ResourcesUsed[];
[
WmiDataId(2),
read
]
uint32 CharacteristicsCount;
[Description (
"The descriptions for each Characteristic are below:\n "
"\n"
"* \"Is Exclusive\"
(value=2) is specified for the test "
"module only if the diagnostic
cannot run more than one test "
"at a time, regardless of how
many SystemElements are "
"supported. Typically, this
occurs when hardware or software "
"constraints prevent the test
from running as multiple, "
"concurrent instances. If the
diagnostic can be run against "
"multiple SystemElements, but
only once per Element, then set "
"the IsExclusiveForMSE boolean
property on the appropriate "
"instances of
DiagnosticTestForMSE. \n"
"\n"
"* If \"Is Interactive\" (value=3) is set, then the
diagnostic "
"displays a message either
before, during or after testing. \n"
"\n"
"* Set \"Is Destructive\" (value=4) if the diagnostic
will "
"destroy data, or reconfigure
the Element that is being "
"tested. \n"
"\n"
"* \"Is Risky\" (value=5) indicates that data loss may
occur "
"if the test is interrupted.
Some tests make copies of data, "
"perform the test, and restore
the data returning the tested "
"entity to its previous
configuration. If the test is "
"interrupted, then loss of data
or reconfiguration of the "
"tested ManagedSystemElement
may occur. \n"
"\n"
"* If \"Is Package\" (value=6) is set, this test is
actually "
"a set of lower level
diagnostics, that are 'packaged' "
"together. \n"
"\n"
"\"Supports PercentOfTestCoverage\"
(value=7) indicates that "
"a request for reduced test
coverage can be specified using "
"the PercentOfTestCoverage
property of Diagnostic Setting. \n"
"\n"
"Also, the values
\"Unknown\" (0) and \"Other\" (1) may be "
"specified. If
\"Other\" is defined, additional detail may be "
"found in the
OtherCharacteristicDescription property of this "
"class."),
read,
Values{"Unknown",
"Other", "Is Exclusive", "Is Interactive",
"Is Destructive",
"Is Risky", "Is Package",
"Supports
PercentOfTestCoverage"},
WmiSizeIs("CharacteristicsCount"),
WmiDataId(3)
]
uint32 Characteristics[];
[
Description (
"Provides additional
information for the Characteristic when "
"its value is set to 1
(\"Other\")."),
WmiDataId(4)
]
string OtherCharacteristicDescription;
//
// Methods
//
[Implemented:toSubclass toInstance,
WmiMethodId(1)
]
void RunTest([IN] WDM_DiagnosticSetting,
[OUT] WDM_DiagnosticResult,
[OUT] uint16 Result);
[Implemented:toSubclass ToInstance,
WmiMethodId(2)
]
void DiscontinueTest([OUT] Boolean
TestingStopped,
[OUT] uint32 Result);
};
// This is
an embedded class
[WMI,
guid("{???????}")
]
class
WDM_DiagnosticSetting
{
[Description (
"Sets the level of warning
messages to be logged. If for "
"example no warning information
is required, the level "
"would be set to \"No
Warnings\" (value=0). Using \"Missing "
"Resources\" (value=1)
will cause warnings to be generated "
"when required resources or
hardware are not found. Setting "
"the value to 2, \"Testing Impacts\", results in both
"
"missing resources and 'test
impact' warnings (for example, "
"multiple retries required) to
be reported."),
Values{"No Warnings",
"Missing Resources",
"Testing Impacts",
"All Warnings"},
Write,
WmiDataId(1)
]
uint16 TestWarningLevel = 3;
[Description (
"When this flag is true, the diagnostic test will report "
"'soft errors'. In this
context, a soft error is a message "
"from the diagnostic reporting
a known defect in the "
"hardware or driver
configuration, or execution "
"environment. Examples are: \"Not enough
memory\", "
"\"Driver IOCTL not
implemented\", \"Video RAM compare "
"failed during polygon fill
test (A known defect in the "
"video chipset)\",
etc."),
Write,
WmiDataId(2)
]
boolean ReportSoftErrors = FALSE;
[Description (
"When this flag is true, the diagnostic test will report "
"'status messages'. In this
context, a status message "
"indicates that the diagnostic
code is at a checkpoint. "
"Examples are: \"Completion of phase 1\", \"Complex
"
"pattern\", etc."),
Write,
WmiDataId(3)
]
boolean ReportStatusMessages = FALSE;
[Description (
"When this flag is true, the test will halt after finding "
"the first error."),
Write,
WmiDataId(4)
]
boolean HaltOnError = FALSE;
[Description (
"When this flag is true, the
test software should attempt "
"to run in an accelerated
fashion either by reducing the "
"coverage or number of tests
performed."),
Write,
WmiDataId(5)
]
boolean QuickMode = FALSE;
[Units ("Percent"), MinValue
(0), MaxValue (100),
Description(
"Requests the diagnostic software to reduce test coverage "
"to the specified
percentage. For example, a hard drive
"
"scan test could be asked to
run at 50%. The most "
"effective way to accomplish
this is for the test software "
"to scan every other track, as
opposed to only scanning the "
"first half of a drive. It is
assumed that the effectiveness "
"of the test is impacted proportional to the percentage of
"
"testing requested. Permissible
values for this property "
"range from 0 to 100. \n"
"This property may not be
applicable to all tests. If it "
"can be set for a test, the
value 7 (\"Supports PercentOf"
"TestCoverage\") should be
entered into the DiagnosticTest's "
"Characteristics array."),
Write,
WmiDataId(6)
]
uint8 PercentOfTestCoverage = 100;
};
//
// Embedded
class
//
[WMI,
guid("{???????}")
]
class
WDM_DiagnosticResult
{
[Description (
"Describes how the test is
progressing. For example, if "
"the test was discontinued, the
TestState will be "
"\"Stopped\"
(value=5), or if testing is currently "
"executing, TestState will be
\"In Progress\" (4)."),
Values{"Unknown", "Other", "Passed",
"Failed",
"In Progress",
"Stopped"},
WmiDataId(1)
]
uint16 TestState = 5;
[Description (
"When \"Other\"
(value=1) is entered in the TestState "
"property,
OtherStateDescription can be used to describe "
"the test's state."),
WmiDataId(1)
]
string OtherStateDescription =
"";
// AMW - Why
is this in the result ????
[Units ("Seconds"),
Description (
"Estimated number of seconds to
perform the Diagnostic"
"Test indicated by the
DiagnosticCreationClassName and "
"DiagnosticName
properties. After the test has
completed, "
"the actual elapsed time can be
determined by subtracting "
"the TestStartTime from the
TestCompletionTime. A similar "
"property is defined in the
association, DiagnosticTest"
"ForMSE. The difference between
the two properties is "
"that the value stored in the
association is a generic "
"test execution time for the
Element and the Test. But, "
"the value here (in
DiagnosticResult) is the estimated "
"time that this instance of
testing would run."),
WmiDataId(1)
]
uint32 EstimatedTimeOfPerforming = 0;
[
WmiDataId(1)
]
uint32 TestResultsCount;
[Description(
"TestResults stores one or more
textual results from the "
"execution of the
DiagnosticTest(s) referenced by the "
"DiagnosticCreationClassName
and DiagnosticName properties. "
"One entry is considered a cell
location in the array. Each "
"entry is time stamped and
contains the following "
"information, in the following
format: \n"
"
yyymmddhhttssoutc|DiagnosticName|Textual message \n"
"Where: \n"
" yyy = year, e.g. 2000 \n"
" mm = month (01 - 12) \n"
" dd = day (01 - 31) \n"
" hh = hour (00 - 24) \n"
" tt = minute (00-59) \n"
" ss = second (00-59) \n"
" o = \"+\" or \"-\" indicating the sign of the
UTC "
"correction field \n"
" utc = offset from
UTC (Universal Coordinated Time) "
"in minutes \n"
" DiagnosticName = string reference to the DiagnosticTest "
"object which was
executed\n"
" Textual message = free form string that is the 'test "
"result'."),
ArrayType ("Ordered"),
WmiSizeIs("TestResultsCount"),
WmiDataId(1)
]
string TestResults[];
[Units ("Percent"), MinValue
(0), MaxValue (100),
Description (
"The percentage of the test
that has executed thus far, if the "
"TestState property is set to
\"In Progress\" or the percentage "
"of the complete test that was
executed if the TestState property "
"is set to any of the completed
states (\"Passed\", \"Failed\" or "
"\"Stopped\"). Final
results may be based on less than 100% coverage "
"due to the parameters defined
in DiagnosticSetting (such as "
"QuickMode,
PercentOfTestCoverage or HaltOnError)." ),
WmiDataId(1)
]
uint8 PercentComplete = 0;
};
In order for the CDM providerconsumer to
access the device driver via the WDM provider there needs to be a set of CDM classes that the
CDM classes need to include a additional
CDM provider specific qualifiers. These qualifiers are used as either runtime
information for the CDM provider or as information to generate the shadow
classes. Each
diagnostic test must have an entire set of CDM classes specifically for that
test and that test alone. Even if the CIM_DiagnosticSettings derived class is
identical for different tests, the CDM provider requires that there be two
different classes.
For classes that are derived from CIM_DiagnosticTest the CDM Provider
requires that it have all of the following class qualifiers.
WdmDiagTest(“Wdm Class Name”)
This
qualifier specifies the name of the WDM_DiagnosticTest derived based class
assigned to this CDM class. If specified it indicates that the driver writer
has included a shadow WDM _Diagnostic Test derived
based
class named “Wdm Class Name” in the driver’s MOF that should be used to
implement this CDM class. No shadow class will be autogenerated.
Guid(“WDM guid”)
This qualifier specifies
the WDM data block guid that is used by the WDM provider to access the device
driver.
CdmDiagResult(“Cdm Class Name”)
This qualifier specifies the name of the CIM_DiagnosticResults derived class that the CDM provider should instantiate to create a results class instance.
CdmDiagSetting(“Cdm Class Name”)
This qualifier specifies the name of the CIM_DiagnosticSetting derived class that the CDM provider should instantiate to create a settings class instance.
CdmPackageList{“CDM Sub Test
1”, “CDM Sub Test 2”, … }
This qualifier indicates
that this class is a package of tests and not an individual test. The value of
the qualifier is an array of strings that contain the names of the
CIM_DiagnosticTest derived classes that compose the package. If this qualifier
is specified then no other CDM specific qualifiers should be specified and no
additional properties should be included in the derived class. No
WDM_DiagnosticTest derived class will be generated for this class as the class
does not represent an actual test implemented by the driver.
CdmDiagResultForMSE(“Cdm
Class Name”)
This qualifier specifies
the name of the CIM_DiagnosticResultForMSE derived class that the CDM provider
should instantiate to create a diagnostic result for MSE class instance.
CdmDiagResultForTest(“Cdm Class
Name”)
This qualifier specifies
the name of the CIM_DiagnosticResultForTest derived class that the CDM provider
should instantiate to create a diagnostic result for test class instance.
CdmDiagTestForMSE(“Cdm Class
Name”)
This qualifier specifies
the name of the CIM_DiagnosticTestForMSE derived class that the CDM provider
should instantiate to create a diagnostic test for MSE class instance.
CdmDiagSettingForTest(“Cdm Class
Name”)
This qualifier specifies
the name of the CIM_DiagnosticSettingForTest derived class that the CDM provider should
instantiate to create a diagnostic setting for test class instance.
CimClassMapping(“Cim Class Name”)
This qualifier specifies
the CIM_LogicalDevice derived class name which has an instance that represents the device
for which this test is written. The CDM provider will map the PnPId for the
CIM_LogicalDevice derived class instance with the PnPId specified in the
instance of the WDM Diagnostic Test shadow class.
WmiDataId(id)
This qualifier is an unsigned integer that
specifies the order of the property within the WDM data block.
If the WdmDiagTest qualifier is specified then
it indicates that the driver writer has also included a WDM_DiagnosticTest
derived class in its MOF to describe how the device driver should be called. In
this case the Guid class qualifier and the WmiDataId property qualifiers should
not be specified and each additional property in the CIM_DiagnosticTest derived
class must have an identical property in the WDM_DiagnosticTest derived class.
If the WdmDiagTest qualifier is not specified
then the guid class qualifier is required. If there are any additional
properties then each of these must have a WmiDataId qualifier. These qualifiers
are needed to generate the related WDM_DiagnosticTest derived class. All WDM
specific class and property qualifiers are copied from the CDM class into the
generated shadow class.
WdmDiagResults(“Wdm Class Name”)
This
qualifier specifies the name of the WDM_ Diagnostic Results derived
class assigned to this CDM class. If specified it indicates
that the driver writer has included a shadow WDM_DiagnosticRsults derived class
named “Wdm Class Name” in the driver’s MOF that should be used to implement
this CDM class. No shadow class will be autogenerated.
WdmDiagOfflineResult(“Wdm Class
Name”)
This qualifier specifies the name of the WDM class that can be queried to retrieve the diagnostic test results from the last offline diagnostic test executed.
CdmDiagTest(“CDM Diagnostic Test
Class
Name”)
This
qualifier specifies the name of the CIM_DiagnosticTest derived class associated
with this class. It is used by the CDM provider as a “back pointer” to the
CIM_DiagnosticTest derived class.
Guid(“WDM guid”)
This qualifier specifies the WDM data block
guid that is used by the WDM provider to access the device driver.
WmiDataId(id)
This qualifier is an unsigned integer that
specifies the order of the property within the WDM data block.
If the WdmDiagResults qualifier is specified
then it indicates that the driver writer has also included a WDM_DiagnosticTest
derived class in its MOF to describe how the device driver should be called. In
this case the Guid class qualifier and the WmiDataId property qualifiers should
not be specified and each additional property in the CIM_DiagnosticResults
derived class must have an identical property in the WDM_DiagnosticResults
derived class.
If the WdmDiagResults qualifier is not
specified then the guid class qualifier is required. If there are any
additional properties then each of these are required to have a WmiDataId
qualifier. These qualifiers are needed to generate the related
WDM_DiagnosticResults derived class. All WDM specific class and property
qualifiers are copied from the CDM class into the generated shadow class.
WdmDiagSettings(“Wdm Class Name”)
This
qualifier specifies the name of the WDM_ Diagnostic Settings derivedbased class assigned
to this CDM class. If specified it indicates that the driver writer
has included a shadow WDM_DiagnosticSettings derived class named “Wdm Class
Name” in the driver’s MOF that should be used to implement this CDM class. No
shadow class will be generated.
WdmDiagSettingsList(“Wdm Class Name”)
This qualifier specifies the name of the WDM class that the CDM provider will query to obtain the list of settings that can be used to execute the test.
CdmDiagTest(“CDM
Diagnostic Test Class Name”)
This
qualifier specifies the name of the CIM_DiagnosticTest derived class associated
with this class. It is used by the CDM provider as a “back pointer” to the
CIM_DiagnosticTest derived class.
Guid(“WDM guid”)
This qualifier specifies the WDM data block
guid that is used by the WDM provider to access the device driver.
WmiDataId(id)
This qualifier is an unsigned integer that
specifies the order of the property within the WDM data block.
If the WdmDiagSettings qualifier is specified
then it indicates that the driver writer has also included a
WDM_DiagnosticSettings derived class in its MOF to describe how the device
driver should be called. In this case the Guid class qualifier and the
WmiDataId property qualifiers should not be specified and each additional
property in the CIM_DiagnosticSettings derived class must have an identical
property in the WDM_DiagnosticSettings derived class.
If the WdmDiagSettings qualifier is not
specified then the guid class qualifier is required. If there are any
additional properties then each of these are required to have a WmiDataId
qualifier. These qualifiers are needed to generate the related
WDM_DiagnosticSettings derived class. All WDM specific class and property qualifiers
are copied from the CDM class into the generated shadow class.
Here is a sample MOF that a driver might specify[AW3]
The CDM
provider architecture needs the existance of a set of shadow WDM classes in
order to communicate with the device driver via the WDM provider. In most cases
creating the shadow classes is a straightforward operation and can be left up
to a software agent to do so. The
appropriate software agent is wmimofck.exe and not the CDM provider itself[AW4].
The CDM provider assumes that all WDM shadow classes are established and the
CdmDiagTest, CdmDiagSettings and CdmDiagResults qualifiers are specified on the
CDM classes.
Wmimofck
will offer functionality that will take a binary mof containing CDM classes
with the appropriate qualifiers as input and generate a .MOF (or .BMF) file
that contains the orginal CDM classes (plus the addition of CdmDiagTest,
CdmDiagSettings and CdmDiagResults qualifiers) and the generated WDM shadow classes[AW5].
The CDM provider will need to implement and populate all
CDM class
instanceses based upon the MOF and the
information in the WDM _Diagnostic Test and WDM Diagnostic Settings List data blocks
returned by the device driver. When the
first CDM class in the set of CDM classes for a test is referenced by a consumer,
the CDM provider will attempt to establish the mapping from the CDM to WDM
classes and build internal data structures to manage the CDM class instances.
The first step in this process is to
find the CIM_DiagnosticTest derived class for the set of CDM classes. This is
done by determining if the first class is derived from CIM_DiagnosticTest and
if not then looking for a CdmDiagTest qualifier on the referenced class. Once
the CIM_DiagnosticTest derived class is found the class specified by the
WdmDiagTest
qualifier is queried all
instances are mapped to instances of the class specified by the CimClassMapping qualifier.
Note that there may be more than one mapping that results and in this case the
CIM_DiagnosticTest derived class can have its RunTest method called with more
than one MSE.
At
this point the CDM provider will use the information returned by the WDM
Diagnostic Test class instance to populate the information in the CIM_DiagnosticTest derived
class instance. The CDM provider will then query the WDM Diagnostic
Settings List class and obtain the available settings for the test and use it to populate the
CIM_DiagnosticSettings derived class instances.
The CDM provider will also use this information to make available instances of the CDM association classes, ie those classes derived from CIM_DiagnosticSettingForTest and CIM_DiagnosticTestForMSE.
When the RunTest method on a CIM_DiagnosticTest derived class is executed the CDM provider will determine the associated WDM Diagnostic Test class and the WDM instance name from the passed MSE via the CIM class mappings. The CDM provider will then copy the passed CIM_DiagnosticSettings class instance into an instance of the WDM Diagnostic Settings class and invoke the WDM Diagnostic Test class RunTest method. This method will return a WDM Diagnostic Result class instance which the CDM provider will copy into a newly created instance of the CIM_DiagnosticResult class. This new instance will be added to the list of diagnostic results and new instances of the CIM_DiagnosticResultForMSE derived class and CIM_DiagnosticResultForTest derived class are created. Results are persisted until the WinMgmt service is restarted or the ClearResults method is invoked.
The device
driver MOF will contain class definitions for the
CIM_DiagnosticTest derived classes that it wants to expose via the CDM
provider. A CIM_DiagnosticTest derived class may be either a
package of tests or may be an actual test. When the CDM provider loads or
detects a new WDM MOF has been added it creates a single instance of each
CIM_DiagnosticTest derived class that is either a package or has an implemented
WDM_DiagnostictTest derived class associated with it[amw6]. If
all tests with a package aren’t implemented by the WDM_DiagnosticTest derived
classes then the package instance is not created.
For classes that are
an actual test each of the classes must include a CDM provider required class
qualifier WdmDiagTest. This qualifier has a
single string value that specifies the class name for the corresponding
WDM_DiagnosticTest derived class that the CDM provider will use to implement
the CIM_DiagnosticTest derived class. The CIM_DiagnosticTest derived classes
must also have a required class qualifier CdmDiagResult.
This qualifier has a single string value that specifies the name of the
CIM_DiagnosticResult derived class that is created to contain the results from
running the test. The CIM_DiagnosticTest derived classes must also have a
required class qualifier CdmDiagSetting.
This qualifier has a single string value that specifies the name of the
CIM_DiagnosticSetting derived class that is used to create instances that
contain the settings for this test.
For classes that are a
package of tests the class definition has a CDM provider required qualifier CdmPackageList.
This qualifier has an array of string values that specify the list of classes
that compose the package.
The
device driver MOF will supply class definitions for CIM_DiagnosticResult
derived classes. Each of these classes has a CDM provider required qualifier WdmDiagResult.
This qualifer has a single string value that specifies the class name for the
corresponding WDM_DiagnosticResult derived class that is returned by the
WDM_DiagnosticTest derived class when its RunTest method is executed. The CDM
provider will create a new instance of the CIM_DiagnosticResult derived class
whenever a test is run by the CDM provider and will populate the values for the
instance of the class from the values in the WDM_DiagnosticResult derived class
CIM_DiagnosticSettings derived class passed to the RunTest method. Note that
any additional properties in the CIM_DiagnosticSettings derived class must have
equivalent (in name and data type) properties in the WDM_DiagnosticSettings
class and the CIM_DiagnoticResult derived class. This is because the settings
from the CIM_DiagnosticSettings derived class instance are copied into the
CIM_DiagnosticResults derived class instance.
The device
driver MOF will supply class definitions for CIM_DiagnosticSetting derived
classes. Each of these classes has a CDM provider required qualifier WdmDiagSetting.
This qualifier has a single string value that specifies the class name for the
corresponding WDM_DiagnosticSetting derived class that is created by the CDM
provider to pass to the RunTest method.
Each instance of this class describes an association between CIM_DiagnosticResult derived class instances and CIM_ManagedSystemElement class instance. To get all of the results for a particular instance of a CIM_ManagedSystemElement you would query CIM_DiagnosticResultForMSE for all instances that contained a particular value for CIM_ManagedSystemElement.
Instances of CIM_DiagnosticResultForMSE are created by the CDM provider whenever it creates a new CIM_DiagnosticResult derived class. Instances are removed whenever the ClearResults method is called.
Each instance of this class describes an association between CIM_DiagnosticResult derived class instances and CIM_DiagnosticTest class instance. To get all of the results for a particular instance of CIM_DiagnosticTest you would query CIM_DiagnosticResultForTest for all instances that contained a particular value for CIM_DiagnosticTest.
Instances of CIM_DiagnosticResultForTerst are created by the CDM provider whenever it creates a new CIM_DiagnosticResult derived class. Instances are removed whenever the ClearResults method is called.
Each instance of this class describes an association between CIM_DiagnosticTest derived class instances and CIM_ManagedSystemElement class instances. To get all of the CIM_ManagedSystemElements that support a particular instance of CIM_DiagnosticTest you would query CIM_DiagnosticTestForMSE for all instances that contained a particular value for CIM_DiagnosticTest. Alternatively you could determine all of the tests a particular managed system element supports.
The CDM
provider needs to establish the associations right when the CDM provider
initializes since diagnostic consumers will expect that they will be available
initially. The CDM provider will enumerate all of its CIM_DiagnosticTest
derived classes and then query each of the associated WDM_DiagnosticTest
derived classes so that it can get a complete list of all WDM_DiagnosticTest
derived class instance and other information including the PnP Ids for the
device stacks that support the tests. CDM provider will then map each of the
PnP ids to CIM_LogicalDevice derived classes. At this point the CDM provider
has enough information to populate all instances of the
CIM_DiagnosticTestForMSE association class[amw7].
Each instance
of this class describes an association between a CIM_DiagnosticTest derived
class instance and another CIM_DiagnosticTest class instance that represents a
package of tests that contains the first CIM_DiagnosticTest derived class
instance.
When the CDM
provider loads it will enumerate all of its CIM_DiagnosticTest derived classes
that have the CdmPackageList qualifier and have
tests implemented by WDM_DiagnosticTest derived classes. With the list of
packages and the list of tests in each package it can create all instances of
this association.
Each
instance of this class describes an association between a CIM_DiagnosticResult
derived class instance and another CIM_DiagnosticResult derived class instance
that represents a package of tests that contains the first CIM_DiagnosticResult
derived class instance.
When the CDM
provider runs a test for a CIM_DiagnosticTest derived class that is a package
it creates the CIM_DiagnosticResult derived class instances and will also
create all instances of the CIM_DiagnosticResultsInPackage association.
CIM_DiagnosticTestSoftware[amw8]
Each
instance of this class describes an association between a CIM_DiagnosticTest derived
class instance and a CIM_SoftwareElement class instance.
Each
instance of this class describes an association between a CIM_DiagnosticTest
derived class instance and a CIM_DiagnosticSetting derived class instance. By
querying for all instances that have a specific CIM_DiagnosticTest you can
determine all of the possible settings that can be used for that test.
For each
device the CDM provider will query a WDM_DiagnosticSetttingsList derived class
which returns an array of WDM_DiagnosticSettings derived embedded classes that
are each a setting appropriate for tests sent to the device. The CDM provider
would then use the returned array of embedded classes to create instances of
the CIM_DiagnosticSetting derived class and create instances of the
CIM_DiagnosticSettingForTest association class.
To be
written
Offline diagnostics are those tests
that cannot be executed while the device is servicing other requests. For example
a disk cannot execute a long duration surface scan while files are opened and
being accessed. The only “safe” time when offline diagnostics can be
executed is during the processing of the IRP_MN_START_DEVICE irp. The basic mechanism to
execute offline diagnostics is to call the device driver with a request to
execute a diagnostic. The device driver will then persist the request in the
registry. The next time that the device receives a IRP_MN_START_DEVICE irp the
device will get the request from the registry, clear the registry value and
execute the test. It will then store the results of the test in its
device extension and continue with the IRP_MN_START_DEVICE processing. Later user mode
consumers can query for the saved results and know the results of the offline
diagnostics.
The CDM provider has support to allow devices to work within
this structure. If CIM_DiagnosticResult derived class has a
WdmDiagOfflineResult class qualifier then this means that the diagnostic may
need to run offline. The value of the qualifier is the WDM class that when queried will report the results of the offline
diagnostic.
When the CDM provider calls the WDM RunTest method it always passes the ExecutionID assigned to the test execution. After executing the RunTest method the CDM Provider examines the TestResults property returned and if it has the value “Offline Pending Execution” and the CIM_DiagnosticResults class has a WdmDiagOfflineResult qualifer then the CDM provider will know that the diagnostic is one that the device driver has requested to be run offline. At this point the CDM provider will call the operating system to request that PnP remove the device stack containing the device and then restart it. If this succeeds then the CDM provider will query the Wdm Diagnostic Offline Result class to retrieve the ExecutionID and the results of the offline diagnostics and use it to fill the CIM_DiagnosticResult derived class. The CDM Provider will validate that the ExecutionID was the one expeeted.
cd
[AW1]An alternative
approach to the cdm prov generating the shadow classes is to have the driver
writer add the shadow classes in the mof itself. The disadvantage of this
scheme is that it is more (and in some cases unneeded) work is needed to be
done by the driver writer and that he will need to maintain 2 classes, rather
than 1. This has the following advantages
·Less
work for CDM provider to do
·CDMProv
Don’t need to worry about keeping classes in sync or cleaning up shadow classes
·If
the CDM base classes add a new property, how is that property represented (ie, what
is WmiDataId) in the generated class ? The driver would be written to the old
base class so the CDM provider would need to know that it should not include
the new base class properties in the derived class. Also what happens when a v2
driver gets on a machine with v1 base classes ? The driver will return extra
stuff that the cdmprov won’t understand. How can we ensure that the data block format will always be understood
by the CDMProv ?
·If
the driver writes the WDM classes itself then they can be used directly via
wmiprov.
I suspect tThe
right compromise wouldsolution is be for
the CDM provider not to generate the classes, but expect the shadow classes to
be in the schema. The shadow classes would then come in the driver’s mof and either
be written by hand or generated by the wmimofck tool.
[AW2]A related approach
would be to skip generating the WDM classes in the schema and maintain that
information in the CDM provider itself. The CDM provider would then call the
device driver directly using undocumented apis and have to parse the WDM data
blocks itself. I believe that generating MOF is a better approach as it more
appropriately layers the functionality. The latter is the
current implementation.
[AW3]Add the sample mof
[AW4]The CDM provider
cannot generate the WDM shadow classes. Consider the case where a driver writes
to v2 of the CDM spec and returns a data block that has data for the properties
in the base v2 CDM class plus some data for a derived class. If this runs on v2
of the CDM provider then all is fine since the provider knows how to split up
the data between the base properties and the derived class properties. Now lets
say the same driver is run on a machine with a v1 CDM provider. The v1 CDM
provider has no idea about the extra base properties in v2 and so will assign
the v2 base property values to the derived class property values. Now this
could be resolved by having a versioning mechanism, but that would introduce
unneeded complexity. In any case if CDM is upgraded to v2 then the driver would
need to be updated to v2 as well if it wanted to implement v2 features. And if
the driver is updated then the driver writer can update its MOF at the same
time. The WDM shadow class description is really a description of an interface
into the device driver and so should be defined by the device driver writer and
carried around by the device driver.
[AW5]Include information
about the rules and process for generating the shadow classes from CDM classes
[amw6]How do we deal with
packages where only some of the tests are implemented by WDM ?
[amw7]The definition for
WDM_DiagnosticTest may not include enough information to completely fill out
CIM_DiagnosticTestForMSE. Revisit the mof and add any needed properties.
[amw8]Does the CDM provider
need to worry about this ? I don’t know how to map pnpids to
CIM_SoftwareElement. Maybe we can get the driver filename from the pnp id and
map that to the CIM_SoftwareElement ?
[amw9]How about a model
where async events can be posted as diagnostic results ? This could apply to
devices that fail to start. Issue: How does failed device mof get into the
schema ? How about exposing eventlog
items as diagnostic results ?
[amw10]Operations
Provider
Load
RunTest
DiscontinueTest
How do Offline Diagnostics fit in
Gather boot
time and failed results and create CIM_DiagnosticResults
Need
methods to schedule offline diags and then to bring them offline
and/or restart
Some
standards for BIST so that dumb code could initiate diags ?? Or
do we
want policy outside kernel ??
Do we
want kernel support for managing the scheduling of diagnostics,
how
they are maintained in the registry, and dispatching requests
to
run those diags ? Or is it the driver's responsibility ??
Logging is really posting DiagResults
asynchronously
How to
persist the logging to safe builds and how to expose this via
WMI
running on safe build ??
Aren't
eventlogs also just DiagResults ???
Supply Driver File and other config info
Preboot/EFI interaction
Recovery console and boot loader support for
enabling diagnostics
[amw11]Include a list of all
of the rules to check for