_Out_ __deref_bcount()

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;
}