[ISAPNP] Fix parsing of complex resource data

- Properly handle the case when the dependent function is placed
  after fixed resources
- Initialize the version and revision fields of resource lists
- Improve validation of resource data
- Add more debug prints

CORE-18562
This commit is contained in:
Dmitry Borisov 2024-05-03 20:39:26 +06:00
parent c1d7087352
commit 76ec8411a4
5 changed files with 551 additions and 825 deletions

View file

@ -20,13 +20,6 @@
#endif /* UNIT_TEST */ #endif /* UNIT_TEST */
typedef enum
{
dfNotStarted,
dfStarted,
dfDone
} DEPEDENT_FUNCTION_STATE;
static static
inline inline
VOID VOID
@ -390,24 +383,6 @@ Peek(
} }
} }
static
CODE_SEG("PAGE")
VOID
PeekCached(
_In_reads_bytes_(Length) PUCHAR ResourceData,
_Out_writes_bytes_all_(Length) PVOID Buffer,
_In_ USHORT Length)
{
PUCHAR Dest = Buffer;
PAGED_CODE();
while (Length--)
{
*Dest++ = *ResourceData++;
}
}
static static
CODE_SEG("PAGE") CODE_SEG("PAGE")
UCHAR UCHAR
@ -454,19 +429,28 @@ ReadTags(
_In_ PUCHAR ReadDataPort, _In_ PUCHAR ReadDataPort,
_Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer, _Out_writes_(ISAPNP_MAX_RESOURCEDATA) PUCHAR Buffer,
_In_ ULONG MaxLength, _In_ ULONG MaxLength,
_Out_ PUSHORT MaxLogDev) _Out_ PUSHORT MaxLogDev,
_Out_ PULONG MaxTagsPerDevice)
{ {
ULONG TagCount = 0;
PAGED_CODE(); PAGED_CODE();
*MaxLogDev = 0; *MaxLogDev = 0;
*MaxTagsPerDevice = 0;
while (TRUE) while (TRUE)
{ {
UCHAR Tag; UCHAR Tag;
USHORT TagLen; USHORT TagLen;
++TagCount;
if (MaxLength < 1) if (MaxLength < 1)
{
DPRINT("Too small tag\n");
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
}
Tag = PeekByte(ReadDataPort); Tag = PeekByte(ReadDataPort);
if (Tag == 0) if (Tag == 0)
@ -487,7 +471,10 @@ ReadTags(
UCHAR Temp[2]; UCHAR Temp[2];
if (MaxLength < sizeof(Temp)) if (MaxLength < sizeof(Temp))
{
DPRINT("Too small tag\n");
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
}
Peek(ReadDataPort, &Temp, sizeof(Temp)); Peek(ReadDataPort, &Temp, sizeof(Temp));
*Buffer++ = Temp[0]; *Buffer++ = Temp[0];
@ -505,17 +492,28 @@ ReadTags(
} }
if (TagLen > MaxLength) if (TagLen > MaxLength)
{
DPRINT("Too large resource data structure\n");
return STATUS_BUFFER_OVERFLOW; return STATUS_BUFFER_OVERFLOW;
}
Peek(ReadDataPort, Buffer, TagLen); Peek(ReadDataPort, Buffer, TagLen);
MaxLength -= TagLen; MaxLength -= TagLen;
Buffer += TagLen; Buffer += TagLen;
if (Tag == ISAPNP_TAG_LOGDEVID) if (Tag == ISAPNP_TAG_LOGDEVID)
(*MaxLogDev)++; {
/* Attempt to guess the allocation size based on the tags available */
*MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount);
TagCount = 0;
if (Tag == ISAPNP_TAG_END) (*MaxLogDev)++;
}
else if (Tag == ISAPNP_TAG_END)
{
*MaxTagsPerDevice = max(*MaxTagsPerDevice, TagCount);
break; break;
}
} }
return STATUS_SUCCESS; return STATUS_SUCCESS;
@ -534,8 +532,8 @@ FreeLogicalDevice(
if (LogDevice->FriendlyName) if (LogDevice->FriendlyName)
ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP); ExFreePoolWithTag(LogDevice->FriendlyName, TAG_ISAPNP);
if (LogDevice->Alternatives) if (LogDevice->Resources)
ExFreePoolWithTag(LogDevice->Alternatives, TAG_ISAPNP); ExFreePoolWithTag(LogDevice->Resources, TAG_ISAPNP);
Entry = LogDevice->CompatibleIdList.Flink; Entry = LogDevice->CompatibleIdList.Flink;
while (Entry != &LogDevice->CompatibleIdList) while (Entry != &LogDevice->CompatibleIdList)
@ -562,15 +560,10 @@ ParseTags(
_Inout_ PISAPNP_LOGICAL_DEVICE LogDevice) _Inout_ PISAPNP_LOGICAL_DEVICE LogDevice)
{ {
USHORT LogDev; USHORT LogDev;
DEPEDENT_FUNCTION_STATE DfState = dfNotStarted; ISAPNP_DEPENDENT_FUNCTION_STATE DfState = dfNotStarted;
PISAPNP_RESOURCE Resource = LogDevice->Resources;
PUCHAR IdStrPos = NULL; PUCHAR IdStrPos = NULL;
USHORT IdStrLen = 0; USHORT IdStrLen = 0;
UCHAR NumberOfIo = 0,
NumberOfIrq = 0,
NumberOfDma = 0,
NumberOfMemRange = 0,
NumberOfMemRange32 = 0,
NumberOfDepedentSet = 0;
PAGED_CODE(); PAGED_CODE();
@ -613,7 +606,7 @@ ParseTags(
goto SkipTag; goto SkipTag;
} }
PeekCached(ResourceData, &Temp, TagLen); RtlCopyMemory(&Temp, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -643,7 +636,7 @@ ParseTags(
if (!CompatibleId) if (!CompatibleId)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
PeekCached(ResourceData, &Temp, TagLen); RtlCopyMemory(&Temp, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -665,30 +658,21 @@ ParseTags(
{ {
PISAPNP_IRQ_DESCRIPTION Description; PISAPNP_IRQ_DESCRIPTION Description;
if (LogDev != 0 || if (LogDev != 0)
(TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) ||
TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) ||
NumberOfIrq >= RTL_NUMBER_OF(LogDevice->Irq))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen > sizeof(ISAPNP_IRQ_DESCRIPTION) ||
TagLen < (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IRQ);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->Irq[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->Irq[NumberOfIrq].Description;
LogDevice->Irq[NumberOfIrq].Index = NumberOfIrq;
++NumberOfIrq;
} }
PeekCached(ResourceData, Description, TagLen); Resource->Type = ISAPNP_RESOURCE_TYPE_IRQ;
Description = &Resource->IrqDescription;
++Resource;
RtlCopyMemory(Description, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1)) if (TagLen == (sizeof(ISAPNP_IRQ_DESCRIPTION) - 1))
@ -708,28 +692,20 @@ ParseTags(
{ {
PISAPNP_DMA_DESCRIPTION Description; PISAPNP_DMA_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_DMA_DESCRIPTION) || if (LogDev != 0)
NumberOfDma >= RTL_NUMBER_OF(LogDevice->Dma))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_DMA_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_DMA);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->Dma[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->Dma[NumberOfDma].Description;
LogDevice->Dma[NumberOfDma].Index = NumberOfDma;
++NumberOfDma;
} }
PeekCached(ResourceData, Description, TagLen); Resource->Type = ISAPNP_RESOURCE_TYPE_DMA;
Description = &Resource->DmaDescription;
++Resource;
RtlCopyMemory(Description, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -744,48 +720,39 @@ ParseTags(
case ISAPNP_TAG_STARTDEP: case ISAPNP_TAG_STARTDEP:
{ {
if (LogDev != 0 || TagLen > 1 || if (LogDev != 0)
NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES)
{
goto SkipTag; goto SkipTag;
if (TagLen > 1)
{
DPRINT1("Invalid tag %x\n", ISAPNP_TAG_STARTDEP);
return STATUS_UNSUCCESSFUL;
} }
if (DfState == dfNotStarted) if (DfState == dfNotStarted)
{ {
LogDevice->Alternatives = ExAllocatePoolZero(PagedPool,
sizeof(ISAPNP_ALTERNATIVES),
TAG_ISAPNP);
if (!LogDevice->Alternatives)
return STATUS_INSUFFICIENT_RESOURCES;
DfState = dfStarted; DfState = dfStarted;
} }
else if (DfState == dfStarted) else if (DfState != dfStarted)
{
++NumberOfDepedentSet;
}
else
{ {
goto SkipTag; goto SkipTag;
} }
++LogDevice->Alternatives->Count; Resource->Type = ISAPNP_RESOURCE_TYPE_START_DEPENDENT;
++Resource;
if (TagLen != 1) if (TagLen != 1)
{ {
LogDevice->Alternatives->Priority[NumberOfDepedentSet] = 1; Resource->Priority = 1;
} }
else else
{ {
PeekCached(ResourceData, RtlCopyMemory(&Resource->Priority, ResourceData, TagLen);
&LogDevice->Alternatives->Priority[NumberOfDepedentSet],
TagLen);
ResourceData += TagLen; ResourceData += TagLen;
} }
DPRINT("*** Start depedent set %u, priority %u ***\n", DPRINT("*** Start dependent set, priority %u ***\n",
NumberOfDepedentSet, Resource->Priority);
LogDevice->Alternatives->Priority[NumberOfDepedentSet]);
break; break;
} }
@ -795,22 +762,14 @@ ParseTags(
if (LogDev != 0 || DfState != dfStarted) if (LogDev != 0 || DfState != dfStarted)
goto SkipTag; goto SkipTag;
Resource->Type = ISAPNP_RESOURCE_TYPE_END_DEPENDENT;
++Resource;
DfState = dfDone; DfState = dfDone;
ResourceData += TagLen; ResourceData += TagLen;
if (HasIoAlternatives(LogDevice->Alternatives)) DPRINT("*** End of dependent set ***\n");
LogDevice->Alternatives->IoIndex = NumberOfIo++;
if (HasIrqAlternatives(LogDevice->Alternatives))
LogDevice->Alternatives->IrqIndex = NumberOfIrq++;
if (HasDmaAlternatives(LogDevice->Alternatives))
LogDevice->Alternatives->DmaIndex = NumberOfDma++;
if (HasMemoryAlternatives(LogDevice->Alternatives))
LogDevice->Alternatives->MemRangeIndex = NumberOfMemRange++;
if (HasMemory32Alternatives(LogDevice->Alternatives))
LogDevice->Alternatives->MemRange32Index = NumberOfMemRange32++;
DPRINT("*** End of depedent set ***\n");
break; break;
} }
@ -819,28 +778,20 @@ ParseTags(
{ {
PISAPNP_IO_DESCRIPTION Description; PISAPNP_IO_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_IO_DESCRIPTION) || if (LogDev != 0)
NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_IO_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_IOPORT);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->Io[NumberOfIo].Description;
LogDevice->Io[NumberOfIo].Index = NumberOfIo;
++NumberOfIo;
} }
PeekCached(ResourceData, Description, TagLen); Resource->Type = ISAPNP_RESOURCE_TYPE_IO;
Description = &Resource->IoDescription;
++Resource;
RtlCopyMemory(Description, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -864,28 +815,20 @@ ParseTags(
ISAPNP_FIXED_IO_DESCRIPTION Temp; ISAPNP_FIXED_IO_DESCRIPTION Temp;
PISAPNP_IO_DESCRIPTION Description; PISAPNP_IO_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION) || if (LogDev != 0)
NumberOfIo >= RTL_NUMBER_OF(LogDevice->Io))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_FIXED_IO_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDIO);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->Io[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->Io[NumberOfIo].Description;
LogDevice->Io[NumberOfIo].Index = NumberOfIo;
++NumberOfIo;
} }
PeekCached(ResourceData, &Temp, TagLen); Resource->Type = ISAPNP_RESOURCE_TYPE_IO;
Description = &Resource->IoDescription;
++Resource;
RtlCopyMemory(&Temp, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
/* Save the address bits [0:9] */ /* Save the address bits [0:9] */
@ -919,7 +862,7 @@ ParseTags(
if (!LogDevice->FriendlyName) if (!LogDevice->FriendlyName)
return STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
PeekCached(IdStrPos, LogDevice->FriendlyName, IdStrLen); RtlCopyMemory(LogDevice->FriendlyName, IdStrPos, IdStrLen);
End = LogDevice->FriendlyName + IdStrLen - 1; End = LogDevice->FriendlyName + IdStrLen - 1;
while (End > LogDevice->FriendlyName && *End == ' ') while (End > LogDevice->FriendlyName && *End == ' ')
@ -929,6 +872,8 @@ ParseTags(
*++End = ANSI_NULL; *++End = ANSI_NULL;
} }
Resource->Type = ISAPNP_RESOURCE_TYPE_END;
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
@ -936,28 +881,23 @@ ParseTags(
{ {
PISAPNP_MEMRANGE_DESCRIPTION Description; PISAPNP_MEMRANGE_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION) || if (LogDev != 0)
NumberOfMemRange >= RTL_NUMBER_OF(LogDevice->MemRange))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_MEMRANGE_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEMRANGE);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->MemRange[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->MemRange[NumberOfMemRange].Description;
LogDevice->MemRange[NumberOfMemRange].Index = NumberOfMemRange;
++NumberOfMemRange;
} }
PeekCached(ResourceData, Description, TagLen); LogDevice->Flags |= ISAPNP_HAS_MEM24_DECODER;
ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM32_DECODER));
Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE;
Description = &Resource->MemRangeDescription;
++Resource;
RtlCopyMemory(Description, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -1004,28 +944,23 @@ ParseTags(
{ {
PISAPNP_MEMRANGE32_DESCRIPTION Description; PISAPNP_MEMRANGE32_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION) || if (LogDev != 0)
NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_MEMRANGE32_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_MEM32RANGE);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->MemRange32[NumberOfMemRange32].Description;
LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32;
++NumberOfMemRange32;
} }
PeekCached(ResourceData, Description, TagLen); LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER;
ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER));
Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32;
Description = &Resource->MemRange32Description;
++Resource;
RtlCopyMemory(Description, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
DPRINT("Found tag 0x%X (len %u)\n" DPRINT("Found tag 0x%X (len %u)\n"
@ -1049,28 +984,23 @@ ParseTags(
ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp; ISAPNP_FIXEDMEMRANGE_DESCRIPTION Temp;
PISAPNP_MEMRANGE32_DESCRIPTION Description; PISAPNP_MEMRANGE32_DESCRIPTION Description;
if (LogDev != 0 || TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION) || if (LogDev != 0)
NumberOfMemRange32 >= RTL_NUMBER_OF(LogDevice->MemRange32))
{
goto SkipTag; goto SkipTag;
}
if (DfState == dfStarted) if (TagLen != sizeof(ISAPNP_FIXEDMEMRANGE_DESCRIPTION))
{ {
if (NumberOfDepedentSet >= ISAPNP_MAX_ALTERNATIVES) DPRINT1("Invalid tag %x\n", ISAPNP_TAG_FIXEDMEM32RANGE);
goto SkipTag; return STATUS_UNSUCCESSFUL;
Description = &LogDevice->Alternatives->MemRange32[NumberOfDepedentSet];
}
else
{
Description = &LogDevice->MemRange32[NumberOfMemRange32].Description;
LogDevice->MemRange32[NumberOfMemRange32].Index = NumberOfMemRange32;
++NumberOfMemRange32;
} }
PeekCached(ResourceData, &Temp, TagLen); LogDevice->Flags |= ISAPNP_HAS_MEM32_DECODER;
ASSERT(!(LogDevice->Flags & ISAPNP_HAS_MEM24_DECODER));
Resource->Type = ISAPNP_RESOURCE_TYPE_MEMRANGE32;
Description = &Resource->MemRange32Description;
++Resource;
RtlCopyMemory(&Temp, ResourceData, TagLen);
ResourceData += TagLen; ResourceData += TagLen;
Description->Information = Temp.Information; Description->Information = Temp.Information;
@ -1121,7 +1051,7 @@ ReadCurrentResources(
WriteLogicalDeviceNumber(LogDevice->LDN); WriteLogicalDeviceNumber(LogDevice->LDN);
/* If the device is not activated by BIOS we just report a NULL resource list */ /* If the device is not activated by BIOS then the device has no boot resources */
if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1)) if (!(ReadByte(ReadDataPort, ISAPNP_ACTIVATE) & 1))
{ {
LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES; LogDevice->Flags &= ~ISAPNP_HAS_RESOURCES;
@ -1217,7 +1147,6 @@ WriteResources(
for (i = 0; i < PartialResourceList->Count; i++) for (i = 0; i < PartialResourceList->Count; i++)
{ {
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &PartialResourceList->PartialDescriptors[i]; PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor = &PartialResourceList->PartialDescriptors[i];
UCHAR Index;
switch (Descriptor->Type) switch (Descriptor->Type)
{ {
@ -1229,10 +1158,9 @@ WriteResources(
Descriptor->u.Port.Start.LowPart + Descriptor->u.Port.Start.LowPart +
Descriptor->u.Port.Length - 1, Descriptor->u.Port.Length - 1,
NULL, NULL,
NULL, NULL);
&Index);
WriteWord(ISAPNP_IOBASE(Index), (USHORT)Descriptor->u.Port.Start.LowPart); WriteWord(ISAPNP_IOBASE(NumberOfIo), (USHORT)Descriptor->u.Port.Start.LowPart);
++NumberOfIo; ++NumberOfIo;
break; break;
@ -1240,10 +1168,10 @@ WriteResources(
case CmResourceTypeInterrupt: case CmResourceTypeInterrupt:
{ {
(VOID)FindIrqDescriptor(LogDevice, Descriptor->u.Interrupt.Level, &Index); (VOID)FindIrqDescriptor(LogDevice, Descriptor->u.Interrupt.Level);
WriteByte(ISAPNP_IRQNO(Index), (UCHAR)Descriptor->u.Interrupt.Level); WriteByte(ISAPNP_IRQNO(NumberOfIrq), (UCHAR)Descriptor->u.Interrupt.Level);
WriteByte(ISAPNP_IRQTYPE(Index), WriteByte(ISAPNP_IRQTYPE(NumberOfIrq),
Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED
? IRQTYPE_HIGH_EDGE : IRQTYPE_LOW_LEVEL); ? IRQTYPE_HIGH_EDGE : IRQTYPE_LOW_LEVEL);
@ -1253,9 +1181,9 @@ WriteResources(
case CmResourceTypeDma: case CmResourceTypeDma:
{ {
(VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel, &Index); (VOID)FindDmaDescriptor(LogDevice, Descriptor->u.Dma.Channel);
WriteByte(ISAPNP_DMACHANNEL(Index), (UCHAR)Descriptor->u.Dma.Channel); WriteByte(ISAPNP_DMACHANNEL(NumberOfDma), (UCHAR)Descriptor->u.Dma.Channel);
++NumberOfDma; ++NumberOfDma;
break; break;
@ -1263,7 +1191,6 @@ WriteResources(
case CmResourceTypeMemory: case CmResourceTypeMemory:
{ {
BOOLEAN Memory32;
UCHAR Information; UCHAR Information;
UCHAR MemoryControl = MEMORY_USE_8_BIT_DECODER; UCHAR MemoryControl = MEMORY_USE_8_BIT_DECODER;
@ -1271,30 +1198,28 @@ WriteResources(
Descriptor->u.Memory.Start.LowPart, Descriptor->u.Memory.Start.LowPart,
Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length - 1, Descriptor->u.Memory.Length - 1,
&Memory32, &Information);
&Information,
&Index);
if (!Memory32) if (LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER)
{ {
if (Information & MEMRANGE_16_BIT_MEMORY_MASK) if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER; MemoryControl = MEMORY_USE_16_BIT_DECODER;
WriteWord(ISAPNP_MEMBASE(Index), WriteWord(ISAPNP_MEMBASE(NumberOfMemory),
(USHORT)(Descriptor->u.Memory.Start.LowPart >> 8)); (USHORT)(Descriptor->u.Memory.Start.LowPart >> 8));
if (ReadMemoryControl(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) if (ReadMemoryControl(ReadDataPort, NumberOfMemory) & MEMORY_UPPER_LIMIT)
{ {
WriteByte(ISAPNP_MEMCONTROL(Index), WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory),
MemoryControl | MEMORY_UPPER_LIMIT); MemoryControl | MEMORY_UPPER_LIMIT);
WriteWord(ISAPNP_MEMLIMIT(Index), WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory),
(USHORT)((Descriptor->u.Memory.Start.LowPart + (USHORT)((Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length) >> 8)); Descriptor->u.Memory.Length) >> 8));
} }
else else
{ {
WriteByte(ISAPNP_MEMCONTROL(Index), MemoryControl); WriteByte(ISAPNP_MEMCONTROL(NumberOfMemory), MemoryControl);
WriteWord(ISAPNP_MEMLIMIT(Index), WriteWord(ISAPNP_MEMLIMIT(NumberOfMemory),
(USHORT)(LENGTH_TO_RANGE_LENGTH(Descriptor-> (USHORT)(LENGTH_TO_RANGE_LENGTH(Descriptor->
u.Memory.Length) >> 8)); u.Memory.Length) >> 8));
} }
@ -1303,7 +1228,7 @@ WriteResources(
} }
else else
{ {
WriteDoubleWord(ISAPNP_MEMBASE32(Index), WriteDoubleWord(ISAPNP_MEMBASE32(NumberOfMemory32),
Descriptor->u.Memory.Start.LowPart); Descriptor->u.Memory.Start.LowPart);
if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY) if ((Information & MEMRANGE_16_BIT_MEMORY_MASK) == MEMRANGE_32_BIT_MEMORY_ONLY)
@ -1311,18 +1236,18 @@ WriteResources(
else if (Information & MEMRANGE_16_BIT_MEMORY_MASK) else if (Information & MEMRANGE_16_BIT_MEMORY_MASK)
MemoryControl = MEMORY_USE_16_BIT_DECODER; MemoryControl = MEMORY_USE_16_BIT_DECODER;
if (ReadMemoryControl32(ReadDataPort, Index) & MEMORY_UPPER_LIMIT) if (ReadMemoryControl32(ReadDataPort, NumberOfMemory32) & MEMORY_UPPER_LIMIT)
{ {
WriteByte(ISAPNP_MEMCONTROL32(Index), WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32),
MemoryControl | MEMORY_UPPER_LIMIT); MemoryControl | MEMORY_UPPER_LIMIT);
WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32),
Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length); Descriptor->u.Memory.Length);
} }
else else
{ {
WriteByte(ISAPNP_MEMCONTROL32(Index), MemoryControl); WriteByte(ISAPNP_MEMCONTROL32(NumberOfMemory32), MemoryControl);
WriteDoubleWord(ISAPNP_MEMLIMIT32(Index), WriteDoubleWord(ISAPNP_MEMLIMIT32(NumberOfMemory32),
LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length)); LENGTH_TO_RANGE_LENGTH(Descriptor->u.Memory.Length));
} }
@ -1501,6 +1426,7 @@ IsaHwFillDeviceList(
NTSTATUS Status; NTSTATUS Status;
UCHAR TempId[3], LogDev; UCHAR TempId[3], LogDev;
ISAPNP_IDENTIFIER Identifier; ISAPNP_IDENTIFIER Identifier;
ULONG MaxTagsPerDevice;
USHORT MaxLogDev; USHORT MaxLogDev;
Wake(Csn); Wake(Csn);
@ -1510,7 +1436,11 @@ IsaHwFillDeviceList(
IsaPnpExtractAscii(TempId, Identifier.VendorId); IsaPnpExtractAscii(TempId, Identifier.VendorId);
Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId); Identifier.ProdId = RtlUshortByteSwap(Identifier.ProdId);
Status = ReadTags(FdoExt->ReadDataPort, ResourceData, ISAPNP_MAX_RESOURCEDATA, &MaxLogDev); Status = ReadTags(FdoExt->ReadDataPort,
ResourceData,
ISAPNP_MAX_RESOURCEDATA,
&MaxLogDev,
&MaxTagsPerDevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn); DPRINT1("Failed to read tags with status 0x%08lx, CSN %u\n", Status, Csn);
@ -1572,6 +1502,16 @@ IsaHwFillDeviceList(
LogDevice->CSN = Csn; LogDevice->CSN = Csn;
LogDevice->LDN = LogDev; LogDevice->LDN = LogDev;
LogDevice->Resources = ExAllocatePoolWithTag(PagedPool,
MaxTagsPerDevice * sizeof(ISAPNP_RESOURCE),
TAG_ISAPNP);
if (!LogDevice->Resources)
{
DPRINT1("Failed to allocate the resources array\n");
FreeLogicalDevice(LogDevice);
goto Deactivate;
}
Status = ParseTags(ResourceData, LogDev, LogDevice); Status = ParseTags(ResourceData, LogDev, LogDevice);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
@ -1644,7 +1584,6 @@ IsaHwConfigureDevice(
Descriptor->u.Port.Start.LowPart + Descriptor->u.Port.Start.LowPart +
Descriptor->u.Port.Length - 1, Descriptor->u.Port.Length - 1,
NULL, NULL,
NULL,
NULL)) NULL))
{ {
return STATUS_RESOURCE_DATA_NOT_FOUND; return STATUS_RESOURCE_DATA_NOT_FOUND;
@ -1658,7 +1597,7 @@ IsaHwConfigureDevice(
if (++NumberOfIrq > RTL_NUMBER_OF(LogicalDevice->Irq)) if (++NumberOfIrq > RTL_NUMBER_OF(LogicalDevice->Irq))
return STATUS_INVALID_PARAMETER_2; return STATUS_INVALID_PARAMETER_2;
if (!FindIrqDescriptor(LogicalDevice, Descriptor->u.Interrupt.Level, NULL)) if (!FindIrqDescriptor(LogicalDevice, Descriptor->u.Interrupt.Level))
return STATUS_RESOURCE_DATA_NOT_FOUND; return STATUS_RESOURCE_DATA_NOT_FOUND;
break; break;
@ -1669,7 +1608,7 @@ IsaHwConfigureDevice(
if (++NumberOfDma > RTL_NUMBER_OF(LogicalDevice->Dma)) if (++NumberOfDma > RTL_NUMBER_OF(LogicalDevice->Dma))
return STATUS_INVALID_PARAMETER_3; return STATUS_INVALID_PARAMETER_3;
if (!FindDmaDescriptor(LogicalDevice, Descriptor->u.Dma.Channel, NULL)) if (!FindDmaDescriptor(LogicalDevice, Descriptor->u.Dma.Channel))
return STATUS_RESOURCE_DATA_NOT_FOUND; return STATUS_RESOURCE_DATA_NOT_FOUND;
break; break;
@ -1686,14 +1625,12 @@ IsaHwConfigureDevice(
Descriptor->u.Memory.Start.LowPart, Descriptor->u.Memory.Start.LowPart,
Descriptor->u.Memory.Start.LowPart + Descriptor->u.Memory.Start.LowPart +
Descriptor->u.Memory.Length - 1, Descriptor->u.Memory.Length - 1,
&Memory32,
NULL,
NULL)) NULL))
{ {
return STATUS_RESOURCE_DATA_NOT_FOUND; return STATUS_RESOURCE_DATA_NOT_FOUND;
} }
if (!Memory32 && (Descriptor->u.Memory.Start.LowPart & 0xFF)) if ((LogicalDevice->Flags & ISAPNP_HAS_MEM24_DECODER) && (Descriptor->u.Memory.Start.LowPart & 0xFF))
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
break; break;

File diff suppressed because it is too large Load diff

View file

@ -151,22 +151,19 @@ FindIoDescriptor(
_In_ ULONG RangeStart, _In_ ULONG RangeStart,
_In_ ULONG RangeEnd, _In_ ULONG RangeEnd,
_Out_opt_ PUCHAR Information, _Out_opt_ PUCHAR Information,
_Out_opt_ PULONG Length, _Out_opt_ PULONG Length);
_Out_opt_ PUCHAR WriteOrder);
CODE_SEG("PAGE") CODE_SEG("PAGE")
BOOLEAN BOOLEAN
FindIrqDescriptor( FindIrqDescriptor(
_In_ PISAPNP_LOGICAL_DEVICE LogDevice, _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
_In_ ULONG Vector, _In_ ULONG Vector);
_Out_opt_ PUCHAR WriteOrder);
CODE_SEG("PAGE") CODE_SEG("PAGE")
BOOLEAN BOOLEAN
FindDmaDescriptor( FindDmaDescriptor(
_In_ PISAPNP_LOGICAL_DEVICE LogDevice, _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
_In_ ULONG Channel, _In_ ULONG Channel);
_Out_opt_ PUCHAR WriteOrder);
CODE_SEG("PAGE") CODE_SEG("PAGE")
BOOLEAN BOOLEAN
@ -174,9 +171,7 @@ FindMemoryDescriptor(
_In_ PISAPNP_LOGICAL_DEVICE LogDevice, _In_ PISAPNP_LOGICAL_DEVICE LogDevice,
_In_ ULONG RangeStart, _In_ ULONG RangeStart,
_In_ ULONG RangeEnd, _In_ ULONG RangeEnd,
_Out_opt_ PBOOLEAN Memory32, _Out_opt_ PUCHAR Information);
_Out_opt_ PUCHAR Information,
_Out_opt_ PUCHAR WriteOrder);
CODE_SEG("PAGE") CODE_SEG("PAGE")
PIO_RESOURCE_REQUIREMENTS_LIST PIO_RESOURCE_REQUIREMENTS_LIST

View file

@ -9,10 +9,7 @@
#pragma once #pragma once
/** @brief Maximum size of resource data structure supported by the driver. */ /** @brief Maximum size of resource data structure supported by the driver. */
#define ISAPNP_MAX_RESOURCEDATA 0x1000 #define ISAPNP_MAX_RESOURCEDATA 0x1000
/** @brief Maximum number of Start DF tags supported by the driver. */
#define ISAPNP_MAX_ALTERNATIVES 8
typedef struct _ISAPNP_IO typedef struct _ISAPNP_IO
{ {
@ -59,23 +56,35 @@ typedef struct _ISAPNP_COMPATIBLE_ID_ENTRY
LIST_ENTRY IdLink; LIST_ENTRY IdLink;
} ISAPNP_COMPATIBLE_ID_ENTRY, *PISAPNP_COMPATIBLE_ID_ENTRY; } ISAPNP_COMPATIBLE_ID_ENTRY, *PISAPNP_COMPATIBLE_ID_ENTRY;
typedef struct _ISAPNP_ALTERNATIVES typedef enum
{ {
ISAPNP_IO_DESCRIPTION Io[ISAPNP_MAX_ALTERNATIVES]; dfNotStarted,
ISAPNP_IRQ_DESCRIPTION Irq[ISAPNP_MAX_ALTERNATIVES]; dfStarted,
ISAPNP_DMA_DESCRIPTION Dma[ISAPNP_MAX_ALTERNATIVES]; dfDone
ISAPNP_MEMRANGE_DESCRIPTION MemRange[ISAPNP_MAX_ALTERNATIVES]; } ISAPNP_DEPENDENT_FUNCTION_STATE;
ISAPNP_MEMRANGE32_DESCRIPTION MemRange32[ISAPNP_MAX_ALTERNATIVES];
UCHAR Priority[ISAPNP_MAX_ALTERNATIVES];
UCHAR IoIndex;
UCHAR IrqIndex;
UCHAR DmaIndex;
UCHAR MemRangeIndex;
UCHAR MemRange32Index;
_Field_range_(0, ISAPNP_MAX_ALTERNATIVES) typedef struct _ISAPNP_RESOURCE
UCHAR Count; {
} ISAPNP_ALTERNATIVES, *PISAPNP_ALTERNATIVES; UCHAR Type;
#define ISAPNP_RESOURCE_TYPE_END 0
#define ISAPNP_RESOURCE_TYPE_IO 1
#define ISAPNP_RESOURCE_TYPE_IRQ 2
#define ISAPNP_RESOURCE_TYPE_DMA 3
#define ISAPNP_RESOURCE_TYPE_MEMRANGE 4
#define ISAPNP_RESOURCE_TYPE_MEMRANGE32 5
#define ISAPNP_RESOURCE_TYPE_START_DEPENDENT 6
#define ISAPNP_RESOURCE_TYPE_END_DEPENDENT 7
union
{
ISAPNP_IO_DESCRIPTION IoDescription;
ISAPNP_IRQ_DESCRIPTION IrqDescription;
ISAPNP_DMA_DESCRIPTION DmaDescription;
ISAPNP_MEMRANGE_DESCRIPTION MemRangeDescription;
ISAPNP_MEMRANGE32_DESCRIPTION MemRange32Description;
UCHAR Priority;
};
} ISAPNP_RESOURCE, *PISAPNP_RESOURCE;
typedef struct _ISAPNP_LOGICAL_DEVICE typedef struct _ISAPNP_LOGICAL_DEVICE
{ {
@ -92,6 +101,12 @@ typedef struct _ISAPNP_LOGICAL_DEVICE
/** Cleared when the device has no boot resources */ /** Cleared when the device has no boot resources */
#define ISAPNP_HAS_RESOURCES 0x00000004 #define ISAPNP_HAS_RESOURCES 0x00000004
/** The card implements 24-bit memory decoder */
#define ISAPNP_HAS_MEM24_DECODER 0x00000008
/** The card implements 32-bit memory decoder */
#define ISAPNP_HAS_MEM32_DECODER 0x00000010
/** /**
* @name The card data. * @name The card data.
* @{ * @{
@ -109,7 +124,7 @@ typedef struct _ISAPNP_LOGICAL_DEVICE
UCHAR LDN; UCHAR LDN;
UCHAR LogVendorId[3]; UCHAR LogVendorId[3];
USHORT LogProdId; USHORT LogProdId;
PISAPNP_ALTERNATIVES Alternatives; PISAPNP_RESOURCE Resources;
PSTR FriendlyName; PSTR FriendlyName;
LIST_ENTRY CompatibleIdList; LIST_ENTRY CompatibleIdList;
@ -120,43 +135,3 @@ typedef struct _ISAPNP_LOGICAL_DEVICE
ISAPNP_MEMRANGE32 MemRange32[4]; ISAPNP_MEMRANGE32 MemRange32[4];
/**@}*/ /**@}*/
} ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE; } ISAPNP_LOGICAL_DEVICE, *PISAPNP_LOGICAL_DEVICE;
FORCEINLINE
BOOLEAN
HasIoAlternatives(
_In_ PISAPNP_ALTERNATIVES Alternatives)
{
return (Alternatives->Io[0].Length != 0);
}
FORCEINLINE
BOOLEAN
HasIrqAlternatives(
_In_ PISAPNP_ALTERNATIVES Alternatives)
{
return (Alternatives->Irq[0].Mask != 0);
}
FORCEINLINE
BOOLEAN
HasDmaAlternatives(
_In_ PISAPNP_ALTERNATIVES Alternatives)
{
return (Alternatives->Dma[0].Mask != 0);
}
FORCEINLINE
BOOLEAN
HasMemoryAlternatives(
_In_ PISAPNP_ALTERNATIVES Alternatives)
{
return (Alternatives->MemRange[0].Length != 0);
}
FORCEINLINE
BOOLEAN
HasMemory32Alternatives(
_In_ PISAPNP_ALTERNATIVES Alternatives)
{
return (Alternatives->MemRange32[0].Length != 0);
}

View file

@ -488,12 +488,6 @@ IsaPdoQueryResources(
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }
if (!(PdoExt->IsaPnpDevice->Flags & ISAPNP_HAS_RESOURCES))
{
Irp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
if (!PdoExt->ResourceList) if (!PdoExt->ResourceList)
return Irp->IoStatus.Status; return Irp->IoStatus.Status;
@ -847,8 +841,8 @@ IsaPnpRemoveLogicalDeviceDO(
if (LogDev->FriendlyName) if (LogDev->FriendlyName)
ExFreePoolWithTag(LogDev->FriendlyName, TAG_ISAPNP); ExFreePoolWithTag(LogDev->FriendlyName, TAG_ISAPNP);
if (LogDev->Alternatives) if (LogDev->Resources)
ExFreePoolWithTag(LogDev->Alternatives, TAG_ISAPNP); ExFreePoolWithTag(LogDev->Resources, TAG_ISAPNP);
Entry = LogDev->CompatibleIdList.Flink; Entry = LogDev->CompatibleIdList.Flink;
while (Entry != &LogDev->CompatibleIdList) while (Entry != &LogDev->CompatibleIdList)
@ -983,18 +977,16 @@ IsaPdoPnp(
break; break;
case IRP_MN_SURPRISE_REMOVAL: case IRP_MN_SURPRISE_REMOVAL:
if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoRemoveDevice(PdoExt, FALSE);
else
Status = IsaReadPortRemoveDevice(PdoExt, FALSE);
break;
case IRP_MN_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE:
{
BOOLEAN FinalRemove = (IrpSp->MinorFunction == IRP_MN_REMOVE_DEVICE);
if (PdoExt->Common.Signature == IsaPnpLogicalDevice) if (PdoExt->Common.Signature == IsaPnpLogicalDevice)
Status = IsaPdoRemoveDevice(PdoExt, TRUE); Status = IsaPdoRemoveDevice(PdoExt, FinalRemove);
else else
Status = IsaReadPortRemoveDevice(PdoExt, TRUE); Status = IsaReadPortRemoveDevice(PdoExt, FinalRemove);
break; break;
}
case IRP_MN_QUERY_PNP_DEVICE_STATE: case IRP_MN_QUERY_PNP_DEVICE_STATE:
Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp); Status = IsaPdoQueryPnpDeviceState(PdoExt, Irp);