Esempio n. 1
0
ACPI_STATUS
AcpiRsCreatePciRoutingTable (
    ACPI_OPERAND_OBJECT     *PackageObject,
    ACPI_BUFFER             *OutputBuffer)
{
    UINT8                   *Buffer;
    ACPI_OPERAND_OBJECT     **TopObjectList;
    ACPI_OPERAND_OBJECT     **SubObjectList;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_SIZE               BufferSizeNeeded = 0;
    UINT32                  NumberOfElements;
    UINT32                  Index;
    ACPI_PCI_ROUTING_TABLE  *UserPrt;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_STATUS             Status;
    ACPI_BUFFER             PathBuffer;


    ACPI_FUNCTION_TRACE (RsCreatePciRoutingTable);


    /* Params already validated, so we don't re-validate here */

    /* Get the required buffer length */

    Status = AcpiRsGetPciRoutingTableLength (PackageObject,
                &BufferSizeNeeded);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
        (UINT32) BufferSizeNeeded));

    /* Validate/Allocate/Clear caller buffer */

    Status = AcpiUtInitializeBuffer (OutputBuffer, BufferSizeNeeded);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /*
     * Loop through the ACPI_INTERNAL_OBJECTS - Each object should be a
     * package that in turn contains an UINT64 Address, a UINT8 Pin,
     * a Name, and a UINT8 SourceIndex.
     */
    TopObjectList    = PackageObject->Package.Elements;
    NumberOfElements = PackageObject->Package.Count;
    Buffer           = OutputBuffer->Pointer;
    UserPrt          = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);

    for (Index = 0; Index < NumberOfElements; Index++)
    {
        /*
         * Point UserPrt past this current structure
         *
         * NOTE: On the first iteration, UserPrt->Length will
         * be zero because we cleared the return buffer earlier
         */
        Buffer += UserPrt->Length;
        UserPrt = ACPI_CAST_PTR (ACPI_PCI_ROUTING_TABLE, Buffer);

        /*
         * Fill in the Length field with the information we have at this point.
         * The minus four is to subtract the size of the UINT8 Source[4] member
         * because it is added below.
         */
        UserPrt->Length = (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);

        /* Each element of the top-level package must also be a package */

        if ((*TopObjectList)->Common.Type != ACPI_TYPE_PACKAGE)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u]) Need sub-package, found %s",
                Index, AcpiUtGetObjectTypeName (*TopObjectList)));
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /* Each sub-package must be of length 4 */

        if ((*TopObjectList)->Package.Count != 4)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u]) Need package of length 4, found length %u",
                Index, (*TopObjectList)->Package.Count));
            return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT);
        }

        /*
         * Dereference the sub-package.
         * The SubObjectList will now point to an array of the four IRQ
         * elements: [Address, Pin, Source, SourceIndex]
         */
        SubObjectList = (*TopObjectList)->Package.Elements;

        /* 1) First subobject: Dereference the PRT.Address */

        ObjDesc = SubObjectList[0];
        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO, "(PRT[%u].Address) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }

        UserPrt->Address = ObjDesc->Integer.Value;

        /* 2) Second subobject: Dereference the PRT.Pin */

        ObjDesc = SubObjectList[1];
        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO, "(PRT[%u].Pin) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }

        UserPrt->Pin = (UINT32) ObjDesc->Integer.Value;

        /*
         * If the BIOS has erroneously reversed the _PRT SourceName (index 2)
         * and the SourceIndex (index 3), fix it. _PRT is important enough to
         * workaround this BIOS error. This also provides compatibility with
         * other ACPI implementations.
         */
        ObjDesc = SubObjectList[3];
        if (!ObjDesc || (ObjDesc->Common.Type != ACPI_TYPE_INTEGER))
        {
            SubObjectList[3] = SubObjectList[2];
            SubObjectList[2] = ObjDesc;

            ACPI_WARNING ((AE_INFO,
                "(PRT[%X].Source) SourceName and SourceIndex are reversed, fixed",
                Index));
        }

        /*
         * 3) Third subobject: Dereference the PRT.SourceName
         * The name may be unresolved (slack mode), so allow a null object
         */
        ObjDesc = SubObjectList[2];
        if (ObjDesc)
        {
            switch (ObjDesc->Common.Type)
            {
            case ACPI_TYPE_LOCAL_REFERENCE:

                if (ObjDesc->Reference.Class != ACPI_REFCLASS_NAME)
                {
                    ACPI_ERROR ((AE_INFO,
                        "(PRT[%u].Source) Need name, found Reference Class 0x%X",
                        Index, ObjDesc->Reference.Class));
                    return_ACPI_STATUS (AE_BAD_DATA);
                }

                Node = ObjDesc->Reference.Node;

                /* Use *remaining* length of the buffer as max for pathname */

                PathBuffer.Length = OutputBuffer->Length -
                                    (UINT32) ((UINT8 *) UserPrt->Source -
                                    (UINT8 *) OutputBuffer->Pointer);
                PathBuffer.Pointer = UserPrt->Source;

                Status = AcpiNsHandleToPathname ((ACPI_HANDLE) Node, &PathBuffer);

                /* +1 to include null terminator */

                UserPrt->Length += (UINT32) ACPI_STRLEN (UserPrt->Source) + 1;
                break;


            case ACPI_TYPE_STRING:

                ACPI_STRCPY (UserPrt->Source, ObjDesc->String.Pointer);

                /*
                 * Add to the Length field the length of the string
                 * (add 1 for terminator)
                 */
                UserPrt->Length += ObjDesc->String.Length + 1;
                break;


            case ACPI_TYPE_INTEGER:
                /*
                 * If this is a number, then the Source Name is NULL, since the
                 * entire buffer was zeroed out, we can leave this alone.
                 *
                 * Add to the Length field the length of the UINT32 NULL
                 */
                UserPrt->Length += sizeof (UINT32);
                break;


            default:

               ACPI_ERROR ((AE_INFO,
                   "(PRT[%u].Source) Need Ref/String/Integer, found %s",
                   Index, AcpiUtGetObjectTypeName (ObjDesc)));
               return_ACPI_STATUS (AE_BAD_DATA);
            }
        }

        /* Now align the current length */

        UserPrt->Length = (UINT32) ACPI_ROUND_UP_TO_64BIT (UserPrt->Length);

        /* 4) Fourth subobject: Dereference the PRT.SourceIndex */

        ObjDesc = SubObjectList[3];
        if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)
        {
            ACPI_ERROR ((AE_INFO,
                "(PRT[%u].SourceIndex) Need Integer, found %s",
                Index, AcpiUtGetObjectTypeName (ObjDesc)));
            return_ACPI_STATUS (AE_BAD_DATA);
        }

        UserPrt->SourceIndex = (UINT32) ObjDesc->Integer.Value;

        /* Point to the next ACPI_OPERAND_OBJECT in the top level package */

        TopObjectList++;
    }

    ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
            OutputBuffer->Pointer, (UINT32) OutputBuffer->Length));
    return_ACPI_STATUS (AE_OK);
}
Esempio n. 2
0
File: rscalc.c Progetto: PyroOS/Pyro
acpi_status
acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
				     acpi_size * buffer_size_needed)
{
	u32 number_of_elements;
	acpi_size temp_size_needed = 0;
	union acpi_operand_object **top_object_list;
	u32 index;
	union acpi_operand_object *package_element;
	union acpi_operand_object **sub_object_list;
	u8 name_found;
	u32 table_index;

	ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);

	number_of_elements = package_object->package.count;

	/*
	 * Calculate the size of the return buffer.
	 * The base size is the number of elements * the sizes of the
	 * structures.  Additional space for the strings is added below.
	 * The minus one is to subtract the size of the u8 Source[1]
	 * member because it is added below.
	 *
	 * But each PRT_ENTRY structure has a pointer to a string and
	 * the size of that string must be found.
	 */
	top_object_list = package_object->package.elements;

	for (index = 0; index < number_of_elements; index++) {

		/* Dereference the sub-package */

		package_element = *top_object_list;

		/*
		 * The sub_object_list will now point to an array of the
		 * four IRQ elements: Address, Pin, Source and source_index
		 */
		sub_object_list = package_element->package.elements;

		/* Scan the irq_table_elements for the Source Name String */

		name_found = FALSE;

		for (table_index = 0; table_index < 4 && !name_found;
		     table_index++) {
			if (*sub_object_list &&	/* Null object allowed */
			    ((ACPI_TYPE_STRING ==
			      ACPI_GET_OBJECT_TYPE(*sub_object_list)) ||
			     ((ACPI_TYPE_LOCAL_REFERENCE ==
			       ACPI_GET_OBJECT_TYPE(*sub_object_list)) &&
			      ((*sub_object_list)->reference.opcode ==
			       AML_INT_NAMEPATH_OP)))) {
				name_found = TRUE;
			} else {
				/* Look at the next element */

				sub_object_list++;
			}
		}

		temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);

		/* Was a String type found? */

		if (name_found) {
			if (ACPI_GET_OBJECT_TYPE(*sub_object_list) ==
			    ACPI_TYPE_STRING) {
				/*
				 * The length String.Length field does not include the
				 * terminating NULL, add 1
				 */
				temp_size_needed += ((acpi_size)
						     (*sub_object_list)->string.
						     length + 1);
			} else {
				temp_size_needed +=
				    acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
			}
		} else {
			/*
			 * If no name was found, then this is a NULL, which is
			 * translated as a u32 zero.
			 */
			temp_size_needed += sizeof(u32);
		}

		/* Round up the size since each element must be aligned */

		temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);

		/* Point to the next union acpi_operand_object */

		top_object_list++;
	}

	/*
	 * Add an extra element to the end of the list, essentially a
	 * NULL terminator
	 */
	*buffer_size_needed =
	    temp_size_needed + sizeof(struct acpi_pci_routing_table);
	return_ACPI_STATUS(AE_OK);
}
Esempio n. 3
0
ACPI_STATUS
AcpiRsGetPciRoutingTableLength (
    ACPI_OPERAND_OBJECT     *PackageObject,
    ACPI_SIZE               *BufferSizeNeeded)
{
    UINT32                  NumberOfElements;
    ACPI_SIZE               TempSizeNeeded = 0;
    ACPI_OPERAND_OBJECT     **TopObjectList;
    UINT32                  Index;
    ACPI_OPERAND_OBJECT     *PackageElement;
    ACPI_OPERAND_OBJECT     **SubObjectList;
    BOOLEAN                 NameFound;
    UINT32                  TableIndex;


    ACPI_FUNCTION_TRACE (RsGetPciRoutingTableLength);


    NumberOfElements = PackageObject->Package.Count;

    /*
     * Calculate the size of the return buffer.
     * The base size is the number of elements * the sizes of the
     * structures. Additional space for the strings is added below.
     * The minus one is to subtract the size of the UINT8 Source[1]
     * member because it is added below.
     *
     * But each PRT_ENTRY structure has a pointer to a string and
     * the size of that string must be found.
     */
    TopObjectList = PackageObject->Package.Elements;

    for (Index = 0; Index < NumberOfElements; Index++)
    {
        /* Dereference the subpackage */

        PackageElement = *TopObjectList;

        /* We must have a valid Package object */

        if (!PackageElement ||
            (PackageElement->Common.Type != ACPI_TYPE_PACKAGE))
        {
            return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
        }

        /*
         * The SubObjectList will now point to an array of the
         * four IRQ elements: Address, Pin, Source and SourceIndex
         */
        SubObjectList = PackageElement->Package.Elements;

        /* Scan the IrqTableElements for the Source Name String */

        NameFound = FALSE;

        for (TableIndex = 0;
             TableIndex < PackageElement->Package.Count && !NameFound;
             TableIndex++)
        {
            if (*SubObjectList && /* Null object allowed */

                ((ACPI_TYPE_STRING ==
                    (*SubObjectList)->Common.Type) ||

                ((ACPI_TYPE_LOCAL_REFERENCE ==
                    (*SubObjectList)->Common.Type) &&

                    ((*SubObjectList)->Reference.Class ==
                        ACPI_REFCLASS_NAME))))
            {
                NameFound = TRUE;
            }
            else
            {
                /* Look at the next element */

                SubObjectList++;
            }
        }

        TempSizeNeeded += (sizeof (ACPI_PCI_ROUTING_TABLE) - 4);

        /* Was a String type found? */

        if (NameFound)
        {
            if ((*SubObjectList)->Common.Type == ACPI_TYPE_STRING)
            {
                /*
                 * The length String.Length field does not include the
                 * terminating NULL, add 1
                 */
                TempSizeNeeded += ((ACPI_SIZE)
                    (*SubObjectList)->String.Length + 1);
            }
            else
            {
                TempSizeNeeded += AcpiNsGetPathnameLength (
                                    (*SubObjectList)->Reference.Node);
            }
        }
        else
        {
            /*
             * If no name was found, then this is a NULL, which is
             * translated as a UINT32 zero.
             */
            TempSizeNeeded += sizeof (UINT32);
        }

        /* Round up the size since each element must be aligned */

        TempSizeNeeded = ACPI_ROUND_UP_TO_64BIT (TempSizeNeeded);

        /* Point to the next ACPI_OPERAND_OBJECT */

        TopObjectList++;
    }

    /*
     * Add an extra element to the end of the list, essentially a
     * NULL terminator
     */
    *BufferSizeNeeded = TempSizeNeeded + sizeof (ACPI_PCI_ROUTING_TABLE);
    return_ACPI_STATUS (AE_OK);
}
Esempio n. 4
0
acpi_status
acpi_rs_create_pci_routing_table(union acpi_operand_object *package_object,
                 struct acpi_buffer *output_buffer)
{
    u8 *buffer;
    union acpi_operand_object **top_object_list;
    union acpi_operand_object **sub_object_list;
    union acpi_operand_object *obj_desc;
    acpi_size buffer_size_needed = 0;
    u32 number_of_elements;
    u32 index;
    struct acpi_pci_routing_table *user_prt;
    struct acpi_namespace_node *node;
    acpi_status status;
    struct acpi_buffer path_buffer;

    ACPI_FUNCTION_TRACE(rs_create_pci_routing_table);

    /* Params already validated, so we don't re-validate here */

    /* Get the required buffer length */

    status = acpi_rs_get_pci_routing_table_length(package_object,
                              &buffer_size_needed);
    if (ACPI_FAILURE(status)) {
        return_ACPI_STATUS(status);
    }

    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "BufferSizeNeeded = %X\n",
              (u32) buffer_size_needed));

    /* Validate/Allocate/Clear caller buffer */

    status = acpi_ut_initialize_buffer(output_buffer, buffer_size_needed);
    if (ACPI_FAILURE(status)) {
        return_ACPI_STATUS(status);
    }

    /*
     * Loop through the ACPI_INTERNAL_OBJECTS - Each object
     * should be a package that in turn contains an
     * acpi_integer Address, a u8 Pin, a Name and a u8 source_index.
     */
    top_object_list = package_object->package.elements;
    number_of_elements = package_object->package.count;
    buffer = output_buffer->pointer;
    user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);

    for (index = 0; index < number_of_elements; index++) {
        int source_name_index = 2;
        int source_index_index = 3;

        /*
         * Point user_prt past this current structure
         *
         * NOTE: On the first iteration, user_prt->Length will
         * be zero because we cleared the return buffer earlier
         */
        buffer += user_prt->length;
        user_prt = ACPI_CAST_PTR(struct acpi_pci_routing_table, buffer);

        /*
         * Fill in the Length field with the information we have at this point.
         * The minus four is to subtract the size of the u8 Source[4] member
         * because it is added below.
         */
        user_prt->length = (sizeof(struct acpi_pci_routing_table) - 4);

        /* Each element of the top-level package must also be a package */

        if (ACPI_GET_OBJECT_TYPE(*top_object_list) != ACPI_TYPE_PACKAGE) {
            ACPI_ERROR((AE_INFO,
                    "(PRT[%X]) Need sub-package, found %s",
                    index,
                    acpi_ut_get_object_type_name
                    (*top_object_list)));
            return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
        }

        /* Each sub-package must be of length 4 */

        if ((*top_object_list)->package.count != 4) {
            ACPI_ERROR((AE_INFO,
                    "(PRT[%X]) Need package of length 4, found length %d",
                    index, (*top_object_list)->package.count));
            return_ACPI_STATUS(AE_AML_PACKAGE_LIMIT);
        }

        /*
         * Dereference the sub-package.
         * The sub_object_list will now point to an array of the four IRQ
         * elements: [Address, Pin, Source, source_index]
         */
        sub_object_list = (*top_object_list)->package.elements;

        /* 1) First subobject: Dereference the PRT.Address */

        obj_desc = sub_object_list[0];
        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
            user_prt->address = obj_desc->integer.value;
        } else {
            ACPI_ERROR((AE_INFO,
                    "(PRT[%X].Address) Need Integer, found %s",
                    index,
                    acpi_ut_get_object_type_name(obj_desc)));
            return_ACPI_STATUS(AE_BAD_DATA);
        }

        /* 2) Second subobject: Dereference the PRT.Pin */

        obj_desc = sub_object_list[1];
        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
            user_prt->pin = (u32) obj_desc->integer.value;
        } else {
            ACPI_ERROR((AE_INFO,
                    "(PRT[%X].Pin) Need Integer, found %s",
                    index,
                    acpi_ut_get_object_type_name(obj_desc)));
            return_ACPI_STATUS(AE_BAD_DATA);
        }

        /*
         * If BIOS erroneously reversed the _PRT source_name and source_index,
         * then reverse them back.
         */
        if (ACPI_GET_OBJECT_TYPE(sub_object_list[3]) !=
            ACPI_TYPE_INTEGER) {
            if (acpi_gbl_enable_interpreter_slack) {
                source_name_index = 3;
                source_index_index = 2;
                printk(KERN_WARNING
                       "ACPI: Handling Garbled _PRT entry\n");
            } else {
                ACPI_ERROR((AE_INFO,
                        "(PRT[%X].source_index) Need Integer, found %s",
                        index,
                        acpi_ut_get_object_type_name
                        (sub_object_list[3])));
                return_ACPI_STATUS(AE_BAD_DATA);
            }
        }

        /*
         * 3) Third subobject: Dereference the PRT.source_name
         * The name may be unresolved (slack mode), so allow a null object
         */
        obj_desc = sub_object_list[source_name_index];
        if (obj_desc) {
            switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
            case ACPI_TYPE_LOCAL_REFERENCE:

                if (obj_desc->reference.opcode !=
                    AML_INT_NAMEPATH_OP) {
                    ACPI_ERROR((AE_INFO,
                            "(PRT[%X].Source) Need name, found reference op %X",
                            index,
                            obj_desc->reference.
                            opcode));
                    return_ACPI_STATUS(AE_BAD_DATA);
                }

                node = obj_desc->reference.node;

                /* Use *remaining* length of the buffer as max for pathname */

                path_buffer.length = output_buffer->length -
                    (u32) ((u8 *) user_prt->source -
                       (u8 *) output_buffer->pointer);
                path_buffer.pointer = user_prt->source;

                status =
                    acpi_ns_handle_to_pathname((acpi_handle)
                                   node,
                                   &path_buffer);

                /* +1 to include null terminator */

                user_prt->length +=
                    (u32) ACPI_STRLEN(user_prt->source) + 1;
                break;

            case ACPI_TYPE_STRING:

                ACPI_STRCPY(user_prt->source,
                        obj_desc->string.pointer);

                /*
                 * Add to the Length field the length of the string
                 * (add 1 for terminator)
                 */
                user_prt->length += obj_desc->string.length + 1;
                break;

            case ACPI_TYPE_INTEGER:
                /*
                 * If this is a number, then the Source Name is NULL, since the
                 * entire buffer was zeroed out, we can leave this alone.
                 *
                 * Add to the Length field the length of the u32 NULL
                 */
                user_prt->length += sizeof(u32);
                break;

            default:

                ACPI_ERROR((AE_INFO,
                        "(PRT[%X].Source) Need Ref/String/Integer, found %s",
                        index,
                        acpi_ut_get_object_type_name
                        (obj_desc)));
                return_ACPI_STATUS(AE_BAD_DATA);
            }
        }

        /* Now align the current length */

        user_prt->length =
            (u32) ACPI_ROUND_UP_TO_64BIT(user_prt->length);

        /* 4) Fourth subobject: Dereference the PRT.source_index */

        obj_desc = sub_object_list[source_index_index];
        if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_INTEGER) {
            user_prt->source_index = (u32) obj_desc->integer.value;
        } else {
            ACPI_ERROR((AE_INFO,
                    "(PRT[%X].SourceIndex) Need Integer, found %s",
                    index,
                    acpi_ut_get_object_type_name(obj_desc)));
            return_ACPI_STATUS(AE_BAD_DATA);
        }

        /* Point to the next union acpi_operand_object in the top level package */

        top_object_list++;
    }

    ACPI_DEBUG_PRINT((ACPI_DB_INFO, "OutputBuffer %p Length %X\n",
              output_buffer->pointer, (u32) output_buffer->length));
    return_ACPI_STATUS(AE_OK);
}