[NTOSKRNL]

- Add 2 parameters to IopUpdateResourceMap to allows for updating different keys
- Implement IopDetectResourceConflict and IopCheckForResourceConflict but don't report the conflicts until we get a resource arbiter
- Halfplement IoReportResourceForDetection

svn path=/trunk/; revision=46654
This commit is contained in:
Cameron Gutman 2010-04-01 22:10:38 +00:00
parent a22393f57a
commit 633c67bdbf
2 changed files with 390 additions and 18 deletions

View file

@ -57,7 +57,7 @@ IopTranslateDeviceResources(
IN ULONG RequiredSize);
NTSTATUS
IopUpdateResourceMap(
IopUpdateResourceMapForPnPDevice(
IN PDEVICE_NODE DeviceNode);
PDEVICE_NODE
@ -163,7 +163,7 @@ IopStartDevice(
Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
if (NT_SUCCESS(Status))
{
Status = IopUpdateResourceMap(DeviceNode);
Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
if (!NT_SUCCESS(Status))
{
DPRINT("IopUpdateResourceMap() failed (Status 0x%08lx)\n", Status);
@ -735,7 +735,7 @@ IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
}
NTSTATUS
IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode)
IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode, PWCHAR Level1Key, PWCHAR Level2Key)
{
NTSTATUS Status;
ULONG Disposition;
@ -760,7 +760,7 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode)
if (!NT_SUCCESS(Status))
return Status;
RtlInitUnicodeString(&KeyName, L"PnP Manager");
RtlInitUnicodeString(&KeyName, Level1Key);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
@ -777,7 +777,7 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode)
if (!NT_SUCCESS(Status))
return Status;
RtlInitUnicodeString(&KeyName, L"PnpManager");
RtlInitUnicodeString(&KeyName, Level2Key);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
@ -857,6 +857,12 @@ IopUpdateResourceMap(IN PDEVICE_NODE DeviceNode)
return STATUS_SUCCESS;
}
NTSTATUS
IopUpdateResourceMapForPnPDevice(IN PDEVICE_NODE DeviceNode)
{
return IopUpdateResourceMap(DeviceNode, L"PnP Manager", L"PnpManager");
}
NTSTATUS
IopSetDeviceInstanceData(HANDLE InstanceKey,
PDEVICE_NODE DeviceNode)
@ -945,7 +951,349 @@ IopSetDeviceInstanceData(HANDLE InstanceKey,
return STATUS_SUCCESS;
}
BOOLEAN
IopCheckForResourceConflict(
IN PCM_RESOURCE_LIST ResourceList1,
IN PCM_RESOURCE_LIST ResourceList2)
{
ULONG i1, i2, ii1, ii2;
BOOLEAN Result = FALSE;
for (i1 = 0; i1 < ResourceList1->Count; i1++)
{
PCM_PARTIAL_RESOURCE_LIST ResList1 = &ResourceList1->List[i1].PartialResourceList;
for (i2 = 0; i2 < ResourceList2->Count; i2++)
{
PCM_PARTIAL_RESOURCE_LIST ResList2 = &ResourceList2->List[i2].PartialResourceList;
for (ii1 = 0; ii1 < ResList1->Count; ii1++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc1 = &ResList1->PartialDescriptors[ii1];
if (ResDesc1->ShareDisposition == CmResourceShareShared)
continue;
for (ii2 = 0; ii2 < ResList2->Count; ii2++)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR ResDesc2 = &ResList2->PartialDescriptors[ii2];
/* We don't care about shared resources */
if (ResDesc2->ShareDisposition == CmResourceShareShared)
continue;
/* Make sure we're comparing the same types */
if (ResDesc1->Type != ResDesc2->Type)
continue;
switch (ResDesc1->Type)
{
case CmResourceTypeMemory:
if ((ResDesc1->u.Memory.Start.QuadPart < ResDesc2->u.Memory.Start.QuadPart &&
ResDesc1->u.Memory.Start.QuadPart + ResDesc1->u.Memory.Length >
ResDesc2->u.Memory.Start.QuadPart) || (ResDesc2->u.Memory.Start.QuadPart <
ResDesc1->u.Memory.Start.QuadPart && ResDesc2->u.Memory.Start.QuadPart +
ResDesc2->u.Memory.Length > ResDesc1->u.Memory.Start.QuadPart))
{
DPRINT1("Resource conflict: Memory (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
ResDesc1->u.Memory.Start.QuadPart, ResDesc1->u.Memory.Start.QuadPart +
ResDesc1->u.Memory.Length, ResDesc2->u.Memory.Start.QuadPart,
ResDesc2->u.Memory.Start.QuadPart + ResDesc2->u.Memory.Length);
Result = TRUE;
goto ByeBye;
}
break;
case CmResourceTypePort:
if ((ResDesc1->u.Port.Start.QuadPart < ResDesc2->u.Port.Start.QuadPart &&
ResDesc1->u.Port.Start.QuadPart + ResDesc1->u.Port.Length >
ResDesc2->u.Port.Start.QuadPart) || (ResDesc2->u.Port.Start.QuadPart <
ResDesc1->u.Port.Start.QuadPart && ResDesc2->u.Port.Start.QuadPart +
ResDesc2->u.Port.Length > ResDesc1->u.Port.Start.QuadPart))
{
DPRINT1("Resource conflict: Port (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
ResDesc1->u.Port.Start.QuadPart, ResDesc1->u.Port.Start.QuadPart +
ResDesc1->u.Port.Length, ResDesc2->u.Port.Start.QuadPart,
ResDesc2->u.Port.Start.QuadPart + ResDesc2->u.Port.Length);
Result = TRUE;
goto ByeBye;
}
break;
case CmResourceTypeInterrupt:
if (ResDesc1->u.Interrupt.Vector == ResDesc2->u.Interrupt.Vector)
{
DPRINT1("Resource conflict: IRQ (0x%x 0x%x vs. 0x%x 0x%x)\n",
ResDesc1->u.Interrupt.Vector, ResDesc1->u.Interrupt.Level,
ResDesc2->u.Interrupt.Vector, ResDesc2->u.Interrupt.Level);
Result = TRUE;
goto ByeBye;
}
break;
case CmResourceTypeBusNumber:
if ((ResDesc1->u.BusNumber.Start < ResDesc2->u.BusNumber.Start &&
ResDesc1->u.BusNumber.Start + ResDesc1->u.BusNumber.Length >
ResDesc2->u.BusNumber.Start) || (ResDesc2->u.BusNumber.Start <
ResDesc1->u.BusNumber.Start && ResDesc2->u.BusNumber.Start +
ResDesc2->u.BusNumber.Length > ResDesc1->u.BusNumber.Start))
{
DPRINT1("Resource conflict: Bus number (0x%x to 0x%x vs. 0x%x to 0x%x)\n",
ResDesc1->u.BusNumber.Start, ResDesc1->u.BusNumber.Start +
ResDesc1->u.BusNumber.Length, ResDesc2->u.BusNumber.Start,
ResDesc2->u.BusNumber.Start + ResDesc2->u.BusNumber.Length);
Result = TRUE;
goto ByeBye;
}
break;
case CmResourceTypeDma:
if (ResDesc1->u.Dma.Channel == ResDesc2->u.Dma.Channel)
{
DPRINT1("Resource conflict: Dma (0x%x 0x%x vs. 0x%x 0x%x)\n",
ResDesc1->u.Dma.Channel, ResDesc1->u.Dma.Port,
ResDesc2->u.Dma.Channel, ResDesc2->u.Dma.Port);
Result = TRUE;
goto ByeBye;
}
break;
}
}
}
}
}
ByeBye:
#ifdef ENABLE_RESOURCE_CONFLICT_DETECTION
return Result;
#else
return FALSE;
#endif
}
NTSTATUS
IopDetectResourceConflict(
IN PCM_RESOURCE_LIST ResourceList)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
HANDLE ResourceMapKey = INVALID_HANDLE_VALUE, ChildKey2 = INVALID_HANDLE_VALUE, ChildKey3 = INVALID_HANDLE_VALUE;
ULONG KeyInformationLength, RequiredLength, KeyValueInformationLength, KeyNameInformationLength;
PKEY_BASIC_INFORMATION KeyInformation;
PKEY_VALUE_PARTIAL_INFORMATION KeyValueInformation;
PKEY_VALUE_BASIC_INFORMATION KeyNameInformation;
ULONG ChildKeyIndex1 = 0, ChildKeyIndex2 = 0, ChildKeyIndex3 = 0;
NTSTATUS Status;
RtlInitUnicodeString(&KeyName, L"\\Registry\\Machine\\HARDWARE\\RESOURCEMAP");
InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE, 0, NULL);
Status = ZwOpenKey(&ResourceMapKey, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
/* The key is missing which means we are the first device */
return STATUS_SUCCESS;
}
while (TRUE)
{
Status = ZwEnumerateKey(ResourceMapKey,
ChildKeyIndex1,
KeyBasicInformation,
NULL,
0,
&RequiredLength);
if (Status == STATUS_NO_MORE_ENTRIES)
break;
else if (Status == STATUS_BUFFER_OVERFLOW || Status == STATUS_BUFFER_TOO_SMALL)
{
KeyInformationLength = RequiredLength;
KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength);
if (!KeyInformation)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
Status = ZwEnumerateKey(ResourceMapKey,
ChildKeyIndex1,
KeyBasicInformation,
KeyInformation,
KeyInformationLength,
&RequiredLength);
}
else
goto cleanup;
ChildKeyIndex1++;
if (!NT_SUCCESS(Status))
goto cleanup;
KeyName.Buffer = KeyInformation->Name;
KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength;
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ResourceMapKey,
NULL);
Status = ZwOpenKey(&ChildKey2, KEY_ENUMERATE_SUB_KEYS | KEY_QUERY_VALUE, &ObjectAttributes);
ExFreePool(KeyInformation);
if (!NT_SUCCESS(Status))
goto cleanup;
while (TRUE)
{
Status = ZwEnumerateKey(ChildKey2,
ChildKeyIndex2,
KeyBasicInformation,
NULL,
0,
&RequiredLength);
if (Status == STATUS_NO_MORE_ENTRIES)
break;
else if (Status == STATUS_BUFFER_TOO_SMALL)
{
KeyInformationLength = RequiredLength;
KeyInformation = ExAllocatePool(PagedPool, KeyInformationLength);
if (!KeyInformation)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
Status = ZwEnumerateKey(ChildKey2,
ChildKeyIndex2,
KeyBasicInformation,
KeyInformation,
KeyInformationLength,
&RequiredLength);
}
else
goto cleanup;
ChildKeyIndex2++;
if (!NT_SUCCESS(Status))
goto cleanup;
KeyName.Buffer = KeyInformation->Name;
KeyName.MaximumLength = KeyName.Length = KeyInformation->NameLength;
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
ChildKey2,
NULL);
Status = ZwOpenKey(&ChildKey3, KEY_QUERY_VALUE, &ObjectAttributes);
ExFreePool(KeyInformation);
if (!NT_SUCCESS(Status))
goto cleanup;
while (TRUE)
{
Status = ZwEnumerateValueKey(ChildKey3,
ChildKeyIndex3,
KeyValuePartialInformation,
NULL,
0,
&RequiredLength);
if (Status == STATUS_NO_MORE_ENTRIES)
break;
else if (Status == STATUS_BUFFER_TOO_SMALL)
{
KeyValueInformationLength = RequiredLength;
KeyValueInformation = ExAllocatePool(PagedPool, KeyValueInformationLength);
if (!KeyValueInformation)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
Status = ZwEnumerateValueKey(ChildKey3,
ChildKeyIndex3,
KeyValuePartialInformation,
KeyValueInformation,
KeyValueInformationLength,
&RequiredLength);
}
else
goto cleanup;
if (!NT_SUCCESS(Status))
goto cleanup;
Status = ZwEnumerateValueKey(ChildKey3,
ChildKeyIndex3,
KeyValueBasicInformation,
NULL,
0,
&RequiredLength);
if (Status == STATUS_BUFFER_TOO_SMALL)
{
KeyNameInformationLength = RequiredLength;
KeyNameInformation = ExAllocatePool(PagedPool, KeyNameInformationLength + sizeof(WCHAR));
if (!KeyNameInformation)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto cleanup;
}
Status = ZwEnumerateValueKey(ChildKey3,
ChildKeyIndex3,
KeyValueBasicInformation,
KeyNameInformation,
KeyNameInformationLength,
&RequiredLength);
}
else
goto cleanup;
ChildKeyIndex3++;
if (!NT_SUCCESS(Status))
goto cleanup;
KeyNameInformation->Name[KeyNameInformation->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
/* Skip translated entries */
if (wcsstr(KeyNameInformation->Name, L".Translated"))
{
ExFreePool(KeyNameInformation);
continue;
}
ExFreePool(KeyNameInformation);
if (IopCheckForResourceConflict(ResourceList,
(PCM_RESOURCE_LIST)KeyValueInformation->Data))
{
ExFreePool(KeyValueInformation);
Status = STATUS_CONFLICTING_ADDRESSES;
goto cleanup;
}
ExFreePool(KeyValueInformation);
}
}
}
cleanup:
if (ResourceMapKey != INVALID_HANDLE_VALUE)
ZwClose(ResourceMapKey);
if (ChildKey2 != INVALID_HANDLE_VALUE)
ZwClose(ChildKey2);
if (ChildKey3 != INVALID_HANDLE_VALUE)
ZwClose(ChildKey3);
if (Status == STATUS_NO_MORE_ENTRIES)
Status = STATUS_SUCCESS;
return Status;
}
NTSTATUS
IopAssignDeviceResources(
IN PDEVICE_NODE DeviceNode,
@ -997,6 +1345,10 @@ IopAssignDeviceResources(
}
RtlCopyMemory(DeviceNode->ResourceList, DeviceNode->BootResources, Size);
Status = IopDetectResourceConflict(DeviceNode->ResourceList);
if (!NT_SUCCESS(Status))
goto ByeBye;
*pRequiredSize = Size;
return STATUS_SUCCESS;
}
@ -1147,6 +1499,10 @@ IopAssignDeviceResources(
DeviceNode->ResourceList->List[0].PartialResourceList.Count = NumberOfResources;
Status = IopDetectResourceConflict(DeviceNode->ResourceList);
if (!NT_SUCCESS(Status))
goto ByeBye;
*pRequiredSize = Size;
return STATUS_SUCCESS;

View file

@ -36,9 +36,13 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
PVOID Context);
NTSTATUS
IopUpdateResourceMap(
IopUpdateResourceMapForPnPDevice(
IN PDEVICE_NODE DeviceNode);
NTSTATUS
IopDetectResourceConflict(
IN PCM_RESOURCE_LIST ResourceList);
/* PRIVATE FUNCTIONS *********************************************************/
PWCHAR
@ -272,7 +276,7 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
{
Status = IopTranslateDeviceResources(DeviceNode, RequiredLength);
if (NT_SUCCESS(Status))
Status = IopUpdateResourceMap(DeviceNode);
Status = IopUpdateResourceMapForPnPDevice(DeviceNode);
}
IopDeviceNodeClearFlag(DeviceNode, DNF_ASSIGNING_RESOURCES);
@ -301,7 +305,7 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject,
}
/*
* @unimplemented
* @halfplemented
*/
NTSTATUS
NTAPI
@ -313,23 +317,35 @@ IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject,
IN ULONG DeviceListSize OPTIONAL,
OUT PBOOLEAN ConflictDetected)
{
static int warned = 0;
if (!warned)
{
DPRINT1("IoReportResourceForDetection partly implemented\n");
warned = 1;
}
PCM_RESOURCE_LIST ResourceList;
NTSTATUS Status;
*ConflictDetected = FALSE;
if (PopSystemPowerDeviceNode && DriverListSize > 0)
if (!DriverList && !DeviceList)
return STATUS_INVALID_PARAMETER;
/* Find the real list */
if (!DriverList)
ResourceList = DeviceList;
else
ResourceList = DriverList;
/* Look for a resource conflict */
Status = IopDetectResourceConflict(ResourceList);
if (Status == STATUS_CONFLICTING_ADDRESSES)
{
/* We hope legacy devices will be enumerated by ACPI */
/* Oh noes */
*ConflictDetected = TRUE;
return STATUS_CONFLICTING_ADDRESSES;
}
else if (NT_SUCCESS(Status))
{
/* Looks like we're good to go */
/* TODO: Claim the resources in the ResourceMap */
}
return STATUS_SUCCESS;
return Status;
}
VOID