Device install without PnP start or perhaps offline driver injection

I have a case where I want to install a driver on a device instance, but
don’t want PnP to try and start the device until after a reboot.

The situation basically could be described as:

  1. I have a running system using a boot storage adapter brand A

  2. I would like my system to instead boot from a brand B storage
    adapter

  3. I can’t physically insert both brand A and brand B storage adapters
    at the same time, so while running on brand A, using the setup API’s, I
    inject a phantom devnode for the brand B adapter (basically slightly
    modified “devcon install” code), and update the drivers on it, since there
    is no actual hardware, the driver instance fails to start, although it does
    try with a PnP start irp failing (expected)

  4. I shutdown the system, switch the boot storage adapter from A to B
    and it boots on the brand B adapter now, I am happy

So my problem is if I try this trick with a brand C storage adapter, it
turns out the brand C driver does not fail the PnP start, even though there
is no hardware. I believe it hangs in the PnP start irp, devcon update
eventually times out, and a kernel debuggers shows the devnode in state
DeviceNodeStartCompletion.

My question: is there a way to install a driver instance, but tell PnP not
to start it? I’ve tried setting the device to disabled before updating the
drivers on the phantom devnode, and it seems to still get enabled and
started.

To complicate matters, the devices are not simple storage adapters, they are
things like NIC cards that that have child devices and need rather more than
a simple entry in the critical device database to work, so really need to
let the class/device installers do whatever they do during driver
installation.

I also don’t own the brand C device, so this is basically a setup of another
companies device problem. I suppose that company never expected a driver
instance to be started when there was no hardware. Lots of drivers do some
validation on PnP start, and fail the start if the validation fails.

It would be viable to have a method where I boot WinPE on the new hardware,
and have it inject the correct boot storage adapter drivers into the offline
OS volume.

I assume this is similar to what must happen during OS install time. WinPE
applies the OS image, and then must inject boot critical device
instances/drivers into the image to make the initial OS boot work. OS setup
must somehow essentially run driver install, with the target registry and
file volume pointing to the OS being installed, not the current running OS.

Any suggestions? Or maybe this is just a normal Windows admin problem and I
am not looking at the corrects docs on how to do this?

Thanks in advance!

Jan

>To complicate matters, the devices are not simple storage adapters, they are things like NIC cards

that that have child devices and need rather more than a simple entry in the critical device database to
work

Maybe it is a good idea to add reasonable defaults to the code, so that this “simple entry in the critical device database” will work?

This “simple entry” is a trivial replacement for an INF, which sets the service name and setup class GUID, and nothing else.

If your stuff will be able to work with such empty/default device registry keys - then this would be great.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

Some of the vendors are dumb (or actually pretty smart) nics, with iSCSI
booting, so you have to have things like network bindings all precreated.
For a dumb nic, we can use a CCDB entry with a DevicePaths entry, although
you still need to get the user mode network class installer to generate all
the right stuff beforehand. It’s a lot more complex than a normal boot
critical storage adapter like a FC adapter.

The nic we have a problem with is not under our control, so we can’t add
defaults in the code when created via the CCDB. We also need to run the
network class installer, which on some NIC’s gets stuck if there is no real
hardware. For network bindings, I believe there are no default values you
can use anyway, although if the code was ours, we could assure PnP start on
non-existing hardware did fail the PnP start cleanly. I assume the driver is
not failing the start either because it’s a bug or else it’s trying to cope
with nic firmware crashes which might make the nic unresponsive (a feature).

A quick poll, if I root enumerate any of YOUR drivers for real hardware,
what happens? It fails PnP start? OS crashes, or something else bad? I can
understand the rational of trying hard to never fail start of boot critical
drivers, which is why I’d like to get the PnP manager to never try to start
it in the first place.

Tricky driver install falls under the category of my role, even if it’s not
kernel code, or written by us.

Jan

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:bounce-407651-
xxxxx@lists.osr.com] On Behalf Of Maxim S. Shatskih
Sent: Thursday, April 08, 2010 5:38 PM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Device install without PnP start or perhaps offline
driver injection

>To complicate matters, the devices are not simple storage adapters,
they are things like NIC cards
>that that have child devices and need rather more than a simple entry
in the critical device database to
>work

Maybe it is a good idea to add reasonable defaults to the code, so that
this “simple entry in the critical device database” will work?

This “simple entry” is a trivial replacement for an INF, which sets the
service name and setup class GUID, and nothing else.

If your stuff will be able to work with such empty/default device
registry keys - then this would be great.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Jan Bottorff wrote:

  1. I can’t physically insert both brand A and brand B storage
    adapters at the same time, so while running on brand A,
    using the setup API’s, I inject a phantom devnode for the
    brand B adapter (basically slightly modified “devcon install”
    code), and update the drivers on it, since there is no actual
    hardware, the driver instance fails to start, although it does
    try with a PnP start irp failing (expected)

Could you clarify exactly what you’re doing here? When I first read this it seemed like you were creating a bogus (say) PCI devnode (I was not aware this was possible, wouldn’t the PCI bus need to create a PDO?), but then later you talk about root enumerating a device, which I obviously get. But if you root enumerate a device, and then install real hardware later, how does that help you? The two instances wouldn’t be the same, I would think.

Yes, I’m creating a bogus PCI devnode, for the purpose of getting a driver
installed for an instance of a device that is not present. If you look at
the docs for SetupDiCreateDeviceInfo, if you don’t set DICD_GENERATE_ID, it
says you supply a full instance id, like
“PCI\VEN_1002&DEV_68D8&SUBSYS_E151174B&REV_00\4&f3a193a&0&0008” for example.
I’m following documented API’s. This is basically devcon install, with a
little tweak.

The effect is, a tree under enum\pci.… is created, a root pdo is created,
all the driver PnP stuff runs to install a driver for the instance (driver
install runs without access to the physical device anyway), the driver is
loaded and started, with the root pdo as a parent. Hopefully the driver
notices there are no assigned resources, and fails the Pnp start. This is
all just like a root enumerated device except on the next boot, the device
is not started, unless there is some other enumerator, like pci.sys, that
creates a pdo with a matching instance id. This works well enough to get a
system to boot on a new boot disk controller.

It turns out, many drivers are totally ok trying to start on a bogus root
pdo, and notice they have no resources. Unfortunately, a driver that’s
important to me, is not happy doing this, and current debugging suggests it
successfully fails the PnP start, but gets stuck while processing the PnP
remove. Since I know the device should never successfully start, it would be
best if I could just tell the PnP subsystem not to even attempt the start.

I’m certainly not the only person who wants to change the boot storage
controller on systems. In my case, I sometimes will want to change from say
a FC attached boot disk to an iSCSI boot disk (the same volume but with a
different access path), so things are a little more complicated (network
adapters need things like network bindings created by user mode code),
especially since I can’t install the FC controller and the iSCSI controller
at the same time, so have no choice but to inject the drivers for a
non-present device. The sticky part of course is you need to forecast what
the PnP instance id is going to be on the target system, which as far as I
know, can only be determined by looking at the value generated by pci.sys on
the target system (or perhaps a like kind system in many cases). For PCI-e
devices with a config space serial number, it’s easy to forecast the
expected instance id.

I suppose it would be possible to write an upper bus filter on the pci
driver that replaced instance id’s with something you knew the algorithm
for. It would be a lot nicer if Microsoft would just document what the
algorithm is. Some careful inspection with the debugger might also determine
the algorithm. Or even better, Microsoft would supply a setup api for
installing non-present devices, that would do all the right stuff. It might
even just be a matter of documenting code already in the OS setup.

Jan

Jan Bottorff wrote:

> 3) I can’t physically insert both brand A and brand B storage
> adapters at the same time, so while running on brand A,
> using the setup API’s, I inject a phantom devnode for the
> brand B adapter (basically slightly modified “devcon install”
> code), and update the drivers on it, since there is no actual
> hardware, the driver instance fails to start, although it does
> try with a PnP start irp failing (expected)

Could you clarify exactly what you’re doing here? When I first read
this it seemed like you were creating a bogus (say) PCI devnode (I was
not aware this was possible, wouldn’t the PCI bus need to create a
PDO?), but then later you talk about root enumerating a device, which I
obviously get. But if you root enumerate a device, and then install
real hardware later, how does that help you? The two instances
wouldn’t be the same, I would think.

Try setting DI_DONOTCALLCONFIGMGR in the device install parameters when you call SetupDiCallClassInstaller to install the new devnode. This *may* configure the device node without actually starting it.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of Jan Bottorff
Sent: Friday, April 09, 2010 2:39 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] Device install without PnP start or perhaps offline driver injection

Yes, I’m creating a bogus PCI devnode, for the purpose of getting a driver installed for an instance of a device that is not present. If you look at the docs for SetupDiCreateDeviceInfo, if you don’t set DICD_GENERATE_ID, it says you supply a full instance id, like “PCI\VEN_1002&DEV_68D8&SUBSYS_E151174B&REV_00\4&f3a193a&0&0008” for example.
I’m following documented API’s. This is basically devcon install, with a little tweak.

The effect is, a tree under enum\pci.… is created, a root pdo is created, all the driver PnP stuff runs to install a driver for the instance (driver install runs without access to the physical device anyway), the driver is loaded and started, with the root pdo as a parent. Hopefully the driver notices there are no assigned resources, and fails the Pnp start. This is all just like a root enumerated device except on the next boot, the device is not started, unless there is some other enumerator, like pci.sys, that creates a pdo with a matching instance id. This works well enough to get a system to boot on a new boot disk controller.

It turns out, many drivers are totally ok trying to start on a bogus root pdo, and notice they have no resources. Unfortunately, a driver that’s important to me, is not happy doing this, and current debugging suggests it successfully fails the PnP start, but gets stuck while processing the PnP remove. Since I know the device should never successfully start, it would be best if I could just tell the PnP subsystem not to even attempt the start.

I’m certainly not the only person who wants to change the boot storage controller on systems. In my case, I sometimes will want to change from say a FC attached boot disk to an iSCSI boot disk (the same volume but with a different access path), so things are a little more complicated (network adapters need things like network bindings created by user mode code), especially since I can’t install the FC controller and the iSCSI controller at the same time, so have no choice but to inject the drivers for a non-present device. The sticky part of course is you need to forecast what the PnP instance id is going to be on the target system, which as far as I know, can only be determined by looking at the value generated by pci.sys on the target system (or perhaps a like kind system in many cases). For PCI-e devices with a config space serial number, it’s easy to forecast the expected instance id.

I suppose it would be possible to write an upper bus filter on the pci driver that replaced instance id’s with something you knew the algorithm for. It would be a lot nicer if Microsoft would just document what the algorithm is. Some careful inspection with the debugger might also determine the algorithm. Or even better, Microsoft would supply a setup api for installing non-present devices, that would do all the right stuff. It might even just be a matter of documenting code already in the OS setup.

Jan

Jan Bottorff wrote:

> 3) I can’t physically insert both brand A and brand B storage
> adapters at the same time, so while running on brand A, using the
> setup API’s, I inject a phantom devnode for the brand B adapter
> (basically slightly modified “devcon install”
> code), and update the drivers on it, since there is no actual
> hardware, the driver instance fails to start, although it does try
> with a PnP start irp failing (expected)

Could you clarify exactly what you’re doing here? When I first read
this it seemed like you were creating a bogus (say) PCI devnode (I was
not aware this was possible, wouldn’t the PCI bus need to create a
PDO?), but then later you talk about root enumerating a device, which
I obviously get. But if you root enumerate a device, and then install
real hardware later, how does that help you? The two instances
wouldn’t be the same, I would think.


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Peter,

Is there an OS in particular that this should work on? The DOCs seem to imply that it ought to work on all of them but thus far on XP-SP3 and Win7 the DevNode is created and started when I try this from a setup application that is trying to create a ‘pre-installed’ (but not presently enumerated) device instance.

I have a slightly different set of requirements from Jan’s scenario but the essence of the device install problem is roughly the same. I have a device enumerator that *will* enumerate the device eventually and I want to pre-install the child device instance in advance of the enumerator actually needing to light it up.

My general approach is to create the instance (as Jan has done) without specifying DICD_GENERATE_ID. I do get the install parameters and modify them to add DI_DONOTCALLCONFIGMGR. I then invoke the CI with DIF_REGISTERDEVICE but the root enumerator still brings the DevNode up.

I have also tried DI_INSTALLDISABLED as well as both together with neither seeming to have much of an effect. Perhaps my expectation is just way wrong.

Regards,

Dave Cattley

From: xxxxx@microsoft.com
To: xxxxx@lists.osr.com
Subject: RE: [ntdev] Device install without PnP start or perhaps offline driver injection
Date: Fri, 9 Apr 2010 23:18:30 +0000

Try setting DI_DONOTCALLCONFIGMGR in the device install parameters when you call SetupDiCallClassInstaller to install the new devnode. This *may* configure the device node without actually starting it.

-p