in Dmf/Modules.Library/Dmf_ResourceHub.c [249:365]
_Out_ __deref_bcount(*TypeSpecificDataLength) VOID* * TypeSpecificData,
_Out_ ULONG* TypeSpecificDataLength,
_Out_opt_ UCHAR** ResourcePath
)
/*++
Routine Description:
Parses a buffer containing a GenericSerialBus ACPI resource descriptor and
returns the serial bus type as well as a pointer to any type specific data.
Arguments:
DmfModule - This Module's handle.
BiosDescriptor - Buffer containing the resource descriptor.
BiosDescriptorLength - Length of buffer in bytes.
SerialBusType - Type of the GenericSerialBus resource (I2C, SPI, etc)
TypeSpecificData - Pointer to the offset in BiosDescriptor containing the
type specific data of the descriptor.
TypeSpecificDataLength - Length of TypeSpecificData in bytes.
ResourcePath - If not null, this string points ACPI BIOS name which this
resource descriptor consumes.
(Generally, the serial bus controller a device/OpRegion uses.)
Return Value:
NTSTATUS
--*/
{
NTSTATUS ntStatus;
PPNP_SERIAL_BUS_DESCRIPTOR serialBusDescriptor;
UCHAR type;
UNREFERENCED_PARAMETER(DmfModule);
ntStatus = STATUS_SUCCESS;
if (ResourcePath != NULL)
{
*ResourcePath = NULL;
}
// Before validating fields of descriptor, verify that buffer itself
// exists and is large enough that it could possibly be valid.
//
if (BiosDescriptor == NULL ||
BiosDescriptorLength < sizeof(PNP_SERIAL_BUS_DESCRIPTOR))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE,
"BiosDescriptorLength=%d sizeof(PNP_SERIAL_BUS_DESCRIPTOR)=%d",
(int)BiosDescriptorLength,
(int)sizeof(PNP_SERIAL_BUS_DESCRIPTOR));
DmfAssert(FALSE);
ntStatus = STATUS_BUFFER_TOO_SMALL;
goto Exit;
}
// Verify that this descriptor is a GenericSerialBus type.
//
type = *(UCHAR*)BiosDescriptor;
if (type != SERIAL_BUS_DESCRIPTOR)
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE,
"type=%d SERIAL_BUS_DESCRIPTOR=%d",
type,
SERIAL_BUS_DESCRIPTOR);
DmfAssert(FALSE);
ntStatus = STATUS_INVALID_PARAMETER;
goto Exit;
}
serialBusDescriptor = (PPNP_SERIAL_BUS_DESCRIPTOR)BiosDescriptor;
// Verify the Length field of the general Serial Bus Connection Descriptor,
// as well as the subtype field are within bounds (which means > min
// size and < size of buffer), and that there is still space for a resource
// path.
//
if ((INTERNAL_SERIAL_BUS_SIZE(serialBusDescriptor) <
sizeof(PNP_SERIAL_BUS_DESCRIPTOR)) ||
(INTERNAL_SERIAL_BUS_SIZE(serialBusDescriptor) >
BiosDescriptorLength) ||
(serialBusDescriptor->TypeDataLength >
(BiosDescriptorLength - sizeof(PNP_SERIAL_BUS_DESCRIPTOR))))
{
TraceEvents(TRACE_LEVEL_ERROR, DMF_TRACE, "Invalid Code Path");
DmfAssert(FALSE);
ntStatus = STATUS_INVALID_PARAMETER;
goto Exit;
}
// Extract SerialBusType.
//
*SerialBusType = (ResourceHub_DIRECTFW_SERIAL_BUS_TYPE)serialBusDescriptor->SerialBusType;
// Extract pointer to type specific data section and resource path.
//
*TypeSpecificData = (UCHAR*)serialBusDescriptor +
RTL_SIZEOF_THROUGH_FIELD(PNP_SERIAL_BUS_DESCRIPTOR,
TypeDataLength);
*TypeSpecificDataLength = serialBusDescriptor->TypeDataLength;
if (ResourcePath != NULL)
{
*ResourcePath = (UCHAR*)serialBusDescriptor +
RTL_SIZEOF_THROUGH_FIELD(PNP_SERIAL_BUS_DESCRIPTOR,
TypeDataLength) +
serialBusDescriptor->TypeDataLength;
}
Exit:
FuncExit(DMF_TRACE, "ntStatus=%!STATUS!", ntStatus);
return ntStatus;
}