Example #1
0
static ACPI_STATUS
AcpiUtCopySimpleObject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *DestDesc)
{
    UINT16                  ReferenceCount;
    ACPI_OPERAND_OBJECT     *NextObject;


    /* Save fields from destination that we don't want to overwrite */

    ReferenceCount = DestDesc->Common.ReferenceCount;
    NextObject = DestDesc->Common.NextObject;

    /* Copy the entire source object over the destination object*/

    ACPI_MEMCPY ((char *) DestDesc, (char *) SourceDesc,
                    sizeof (ACPI_OPERAND_OBJECT));

    /* Restore the saved fields */

    DestDesc->Common.ReferenceCount = ReferenceCount;
    DestDesc->Common.NextObject = NextObject;

    /* New object is not static, regardless of source */

    DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;

    /* Handle the objects with extra data */

    switch (ACPI_GET_OBJECT_TYPE (DestDesc))
    {
    case ACPI_TYPE_BUFFER:
        /*
         * Allocate and copy the actual buffer if and only if:
         * 1) There is a valid buffer pointer
         * 2) The buffer has a length > 0
         */
        if ((SourceDesc->Buffer.Pointer) &&
            (SourceDesc->Buffer.Length))
        {
            DestDesc->Buffer.Pointer =
                ACPI_ALLOCATE (SourceDesc->Buffer.Length);
            if (!DestDesc->Buffer.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual buffer data */

            ACPI_MEMCPY (DestDesc->Buffer.Pointer,
                    SourceDesc->Buffer.Pointer,
                    SourceDesc->Buffer.Length);
        }
        break;

    case ACPI_TYPE_STRING:
        /*
         * Allocate and copy the actual string if and only if:
         * 1) There is a valid string pointer
         * (Pointer to a NULL string is allowed)
         */
        if (SourceDesc->String.Pointer)
        {
            DestDesc->String.Pointer =
                ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
            if (!DestDesc->String.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual string data */

            ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
                         (ACPI_SIZE) SourceDesc->String.Length + 1);
        }
        break;

    case ACPI_TYPE_LOCAL_REFERENCE:
        /*
         * We copied the reference object, so we now must add a reference
         * to the object pointed to by the reference
         *
         * DDBHandle reference (from Load/LoadTable is a special reference,
         * it's Reference.Object is the table index, so does not need to
         * increase the reference count
         */
        if (SourceDesc->Reference.Opcode == AML_LOAD_OP)
        {
            break;
        }

        AcpiUtAddReference (SourceDesc->Reference.Object);
        break;

    case ACPI_TYPE_REGION:
        /*
         * We copied the Region Handler, so we now must add a reference
         */
        if (DestDesc->Region.Handler)
        {
            AcpiUtAddReference (DestDesc->Region.Handler);
        }
        break;

    default:
        /* Nothing to do for other simple objects */
        break;
    }

    return (AE_OK);
}
Example #2
0
ACPI_STATUS
AcpiExStoreStringToString (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *TargetDesc)
{
    UINT32                  Length;
    UINT8                   *Buffer;


    ACPI_FUNCTION_TRACE_PTR (ExStoreStringToString, SourceDesc);


    /* If Source and Target are the same, just return */

    if (SourceDesc == TargetDesc)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* We know that SourceDesc is a string by now */

    Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->String.Pointer);
    Length = SourceDesc->String.Length;

    /*
     * Replace existing string value if it will fit and the string
     * pointer is not a static pointer (part of an ACPI table)
     */
    if ((Length < TargetDesc->String.Length) &&
       (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
    {
        /*
         * String will fit in existing non-static buffer.
         * Clear old string and copy in the new one
         */
        ACPI_MEMSET (TargetDesc->String.Pointer, 0,
            (ACPI_SIZE) TargetDesc->String.Length + 1);
        ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length);
    }
    else
    {
        /*
         * Free the current buffer, then allocate a new buffer
         * large enough to hold the value
         */
        if (TargetDesc->String.Pointer &&
           (!(TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER)))
        {
            /* Only free if not a pointer into the DSDT */

            ACPI_FREE (TargetDesc->String.Pointer);
        }

        TargetDesc->String.Pointer = ACPI_ALLOCATE_ZEROED (
                                        (ACPI_SIZE) Length + 1);
        if (!TargetDesc->String.Pointer)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
        ACPI_MEMCPY (TargetDesc->String.Pointer, Buffer, Length);
    }

    /* Set the new target length */

    TargetDesc->String.Length = Length;
    return_ACPI_STATUS (AE_OK);
}
Example #3
0
acpi_status
acpi_ut_copy_esimple_to_isimple (
	union acpi_object               *external_object,
	union acpi_operand_object       **ret_internal_object)
{
	union acpi_operand_object       *internal_object;


	ACPI_FUNCTION_TRACE ("ut_copy_esimple_to_isimple");


	/*
	 * Simple types supported are: String, Buffer, Integer
	 */
	switch (external_object->type) {
	case ACPI_TYPE_STRING:
	case ACPI_TYPE_BUFFER:
	case ACPI_TYPE_INTEGER:

		internal_object = acpi_ut_create_internal_object ((u8) external_object->type);
		if (!internal_object) {
			return_ACPI_STATUS (AE_NO_MEMORY);
		}
		break;

	default:
		/* All other types are not supported */

		return_ACPI_STATUS (AE_SUPPORT);
	}


	/* Must COPY string and buffer contents */

	switch (external_object->type) {
	case ACPI_TYPE_STRING:

		internal_object->string.pointer =
			ACPI_MEM_CALLOCATE ((acpi_size) external_object->string.length + 1);
		if (!internal_object->string.pointer) {
			goto error_exit;
		}

		ACPI_MEMCPY (internal_object->string.pointer,
				  external_object->string.pointer,
				  external_object->string.length);

		internal_object->string.length = external_object->string.length;
		break;


	case ACPI_TYPE_BUFFER:

		internal_object->buffer.pointer =
			ACPI_MEM_CALLOCATE (external_object->buffer.length);
		if (!internal_object->buffer.pointer) {
			goto error_exit;
		}

		ACPI_MEMCPY (internal_object->buffer.pointer,
				  external_object->buffer.pointer,
				  external_object->buffer.length);

		internal_object->buffer.length = external_object->buffer.length;
		break;


	case ACPI_TYPE_INTEGER:

		internal_object->integer.value  = external_object->integer.value;
		break;

	default:
		/* Other types can't get here */
		break;
	}

	*ret_internal_object = internal_object;
	return_ACPI_STATUS (AE_OK);


error_exit:
	acpi_ut_remove_reference (internal_object);
	return_ACPI_STATUS (AE_NO_MEMORY);
}
static ACPI_STATUS
OslTableInitialize (
    void)
{
    char                    Buffer[32];
    ACPI_TABLE_HEADER       *MappedTable;
    UINT8                   *TableAddress;
    UINT8                   *RsdpAddress;
    ACPI_PHYSICAL_ADDRESS   RsdpBase;
    ACPI_SIZE               RsdpSize;
    ACPI_STATUS             Status;
    u_long                  Address = 0;
    size_t                  Length = sizeof (Address);


    /* Get main ACPI tables from memory on first invocation of this function */

    if (Gbl_MainTableObtained)
    {
        return (AE_OK);
    }

    /* Attempt to use kenv or sysctl to find RSD PTR record. */

    if (Gbl_RsdpBase)
    {
        Address = Gbl_RsdpBase;
    }
    else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
    {
        Address = ACPI_STRTOUL (Buffer, NULL, 0);
    }
    if (!Address)
    {
        if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
        {
            Address = 0;
        }
    }
    if (Address)
    {
        RsdpBase = Address;
        RsdpSize = sizeof (Gbl_Rsdp);
    }
    else
    {
        RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
        RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
    }

    /* Get RSDP from memory */

    RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
    if (!RsdpAddress)
    {
        return (AE_BAD_ADDRESS);
    }

    /* Search low memory for the RSDP */

    TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
    if (!TableAddress)
    {
        AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
        return (AE_ERROR);
    }

    ACPI_MEMCPY (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
    AcpiOsUnmapMemory (RsdpAddress, RsdpSize);

    /* Get XSDT from memory */

    if (Gbl_Rsdp.Revision)
    {
        Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
            ACPI_SIG_XSDT, &MappedTable);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }

        Gbl_Revision = 2;
        Gbl_Xsdt = calloc (1, MappedTable->Length);
        if (!Gbl_Xsdt)
        {
            fprintf (stderr,
                "XSDT: Could not allocate buffer for table of length %X\n",
                MappedTable->Length);
            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
            return (AE_NO_MEMORY);
        }

        ACPI_MEMCPY (Gbl_Xsdt, MappedTable, MappedTable->Length);
        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    }

    /* Get RSDT from memory */

    if (Gbl_Rsdp.RsdtPhysicalAddress)
    {
        Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
            ACPI_SIG_RSDT, &MappedTable);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }

        Gbl_Rsdt = calloc (1, MappedTable->Length);
        if (!Gbl_Rsdt)
        {
            fprintf (stderr,
                "RSDT: Could not allocate buffer for table of length %X\n",
                MappedTable->Length);
            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
            return (AE_NO_MEMORY);
        }

        ACPI_MEMCPY (Gbl_Rsdt, MappedTable, MappedTable->Length);
        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    }

    /* Get FADT from memory */

    if (Gbl_Revision)
    {
        Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
    }
    else
    {
        Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
    }

    if (!Gbl_FadtAddress)
    {
        fprintf(stderr, "FADT: Table could not be found\n");
        return (AE_ERROR);
    }

    Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Gbl_Fadt = calloc (1, MappedTable->Length);
    if (!Gbl_Fadt)
    {
        fprintf (stderr,
            "FADT: Could not allocate buffer for table of length %X\n",
            MappedTable->Length);
        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
        return (AE_NO_MEMORY);
    }

    ACPI_MEMCPY (Gbl_Fadt, MappedTable, MappedTable->Length);
    AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    Gbl_MainTableObtained = TRUE;
    return (AE_OK);
}
Example #5
0
acpi_status
acpi_ev_create_gpe_block (
	struct acpi_namespace_node      *gpe_device,
	struct acpi_generic_address     *gpe_block_address,
	u32                             register_count,
	u8                              gpe_block_base_number,
	u32                             interrupt_level,
	struct acpi_gpe_block_info      **return_gpe_block)
{
	struct acpi_gpe_block_info      *gpe_block;
	acpi_status                     status;


	ACPI_FUNCTION_TRACE ("ev_create_gpe_block");


	if (!register_count) {
		return_ACPI_STATUS (AE_OK);
	}

	/* Allocate a new GPE block */

	gpe_block = ACPI_MEM_CALLOCATE (sizeof (struct acpi_gpe_block_info));
	if (!gpe_block) {
		return_ACPI_STATUS (AE_NO_MEMORY);
	}

	/* Initialize the new GPE block */

	gpe_block->register_count = register_count;
	gpe_block->block_base_number = gpe_block_base_number;

	ACPI_MEMCPY (&gpe_block->block_address, gpe_block_address, sizeof (struct acpi_generic_address));

	/* Create the register_info and event_info sub-structures */

	status = acpi_ev_create_gpe_info_blocks (gpe_block);
	if (ACPI_FAILURE (status)) {
		ACPI_MEM_FREE (gpe_block);
		return_ACPI_STATUS (status);
	}

	/* Install the new block in the global list(s) */

	status = acpi_ev_install_gpe_block (gpe_block, interrupt_level);
	if (ACPI_FAILURE (status)) {
		ACPI_MEM_FREE (gpe_block);
		return_ACPI_STATUS (status);
	}

	/* Dump info about this GPE block */

	ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "GPE %02d to %02d [%4.4s] %d regs at %8.8X%8.8X on int %d\n",
		gpe_block->block_base_number,
		(u32) (gpe_block->block_base_number +
				((gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH) -1)),
		gpe_device->name.ascii,
		gpe_block->register_count,
		ACPI_HIDWORD (gpe_block->block_address.address),
		ACPI_LODWORD (gpe_block->block_address.address),
		interrupt_level));

	/* Find all GPE methods (_Lxx, _Exx) for this block */

	status = acpi_ns_walk_namespace (ACPI_TYPE_METHOD, gpe_device,
			  ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_save_method_info,
			  gpe_block, NULL);

	/* Return the new block */

	if (return_gpe_block) {
		(*return_gpe_block) = gpe_block;
	}

	return_ACPI_STATUS (AE_OK);
}
Example #6
0
static ACPI_STATUS
AcpiUtCopyEsimpleToIsimple (
    ACPI_OBJECT             *ExternalObject,
    ACPI_OPERAND_OBJECT     **RetInternalObject)
{
    ACPI_OPERAND_OBJECT     *InternalObject;


    ACPI_FUNCTION_TRACE (UtCopyEsimpleToIsimple);


    /*
     * Simple types supported are: String, Buffer, Integer
     */
    switch (ExternalObject->Type)
    {
    case ACPI_TYPE_STRING:
    case ACPI_TYPE_BUFFER:
    case ACPI_TYPE_INTEGER:
    case ACPI_TYPE_LOCAL_REFERENCE:

        InternalObject = AcpiUtCreateInternalObject (
                             (UINT8) ExternalObject->Type);
        if (!InternalObject)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }
        break;

    case ACPI_TYPE_ANY: /* This is the case for a NULL object */

        *RetInternalObject = NULL;
        return_ACPI_STATUS (AE_OK);

    default:
        /* All other types are not supported */

        ACPI_ERROR ((AE_INFO,
                     "Unsupported object type, cannot convert to internal object: %s",
                     AcpiUtGetTypeName (ExternalObject->Type)));

        return_ACPI_STATUS (AE_SUPPORT);
    }


    /* Must COPY string and buffer contents */

    switch (ExternalObject->Type)
    {
    case ACPI_TYPE_STRING:

        InternalObject->String.Pointer =
            ACPI_ALLOCATE_ZEROED ((ACPI_SIZE)
                                  ExternalObject->String.Length + 1);

        if (!InternalObject->String.Pointer)
        {
            goto ErrorExit;
        }

        ACPI_MEMCPY (InternalObject->String.Pointer,
                     ExternalObject->String.Pointer,
                     ExternalObject->String.Length);

        InternalObject->String.Length  = ExternalObject->String.Length;
        break;


    case ACPI_TYPE_BUFFER:

        InternalObject->Buffer.Pointer =
            ACPI_ALLOCATE_ZEROED (ExternalObject->Buffer.Length);
        if (!InternalObject->Buffer.Pointer)
        {
            goto ErrorExit;
        }

        ACPI_MEMCPY (InternalObject->Buffer.Pointer,
                     ExternalObject->Buffer.Pointer,
                     ExternalObject->Buffer.Length);

        InternalObject->Buffer.Length  = ExternalObject->Buffer.Length;

        /* Mark buffer data valid */

        InternalObject->Buffer.Flags |= AOPOBJ_DATA_VALID;
        break;


    case ACPI_TYPE_INTEGER:

        InternalObject->Integer.Value   = ExternalObject->Integer.Value;
        break;

    case ACPI_TYPE_LOCAL_REFERENCE:

        /* TBD: should validate incoming handle */

        InternalObject->Reference.Class = ACPI_REFCLASS_NAME;
        InternalObject->Reference.Node = ExternalObject->Reference.Handle;
        break;

    default:
        /* Other types can't get here */
        break;
    }

    *RetInternalObject = InternalObject;
    return_ACPI_STATUS (AE_OK);


ErrorExit:
    AcpiUtRemoveReference (InternalObject);
    return_ACPI_STATUS (AE_NO_MEMORY);
}
Example #7
0
ACPI_STATUS
AeBuildLocalTables (
    UINT32                  TableCount,
    AE_TABLE_DESC           *TableList)
{
    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
    UINT32                  XsdtSize;
    AE_TABLE_DESC           *NextTable;
    UINT32                  NextIndex;
    ACPI_TABLE_FADT         *ExternalFadt = NULL;


    /*
     * Update the table count. For DSDT, it is not put into the XSDT. For
     * FADT, this is already accounted for since we usually install a
     * local FADT.
     */
    NextTable = TableList;
    while (NextTable)
    {
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
            ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            TableCount--;
        }
        NextTable = NextTable->Next;
    }

    XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64));

    /* Build an XSDT */

    LocalXSDT = AcpiOsAllocate (XsdtSize);
    if (!LocalXSDT)
    {
        return (AE_NO_MEMORY);
    }

    ACPI_MEMSET (LocalXSDT, 0, XsdtSize);
    ACPI_MOVE_NAME (LocalXSDT->Header.Signature, ACPI_SIG_XSDT);
    LocalXSDT->Header.Length = XsdtSize;
    LocalXSDT->Header.Revision = 1;

    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);

    /*
     * Install the user tables. The DSDT must be installed in the FADT.
     * All other tables are installed directly into the XSDT.
     */
    NextIndex = BASE_XSDT_TABLES;
    NextTable = TableList;
    while (NextTable)
    {
        /*
         * Incoming DSDT or FADT are special cases. All other tables are
         * just immediately installed into the XSDT.
         */
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
        {
            if (DsdtAddress)
            {
                printf ("Already found a DSDT, only one allowed\n");
                return (AE_ALREADY_EXISTS);
            }

            /* The incoming user table is a DSDT */

            DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
            LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else
        {
            /* Install the table in the XSDT */

            LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            NextIndex++;
        }

        NextTable = NextTable->Next;
    }

    /* Build an RSDP */

    ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
    ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature);
    ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6);
    LocalRSDP.Revision = 2;
    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
    LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT);

    /* Set checksums for both XSDT and RSDP */

    LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) LocalXSDT, LocalXSDT->Header.Length);
    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);

    if (!DsdtAddress)
    {
        return (AE_SUPPORT);
    }

    if (ExternalFadt)
    {
        /*
         * Use the external FADT, but we must update the DSDT/FACS addresses
         * as well as the checksum
         */
        ExternalFadt->Dsdt = DsdtAddress;
        ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
        {
            ExternalFadt->XDsdt = DsdtAddress;
            ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
        }
        /* Complete the FADT with the checksum */

        ExternalFadt->Header.Checksum = 0;
        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) ExternalFadt, ExternalFadt->Header.Length);
    }
    else
    {
        /*
         * Build a local FADT so we can test the hardware/event init
         */
        ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));
        ACPI_MOVE_NAME (LocalFADT.Header.Signature, ACPI_SIG_FADT);

        /* Setup FADT header and DSDT/FACS addresses */

        LocalFADT.Dsdt = 0;
        LocalFADT.Facs = 0;

        LocalFADT.XDsdt = DsdtAddress;
        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        LocalFADT.Header.Revision = 3;
        LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT);

        /* Miscellaneous FADT fields */

        LocalFADT.Gpe0BlockLength = 16;
        LocalFADT.Gpe0Block = 0x00001234;

        LocalFADT.Gpe1BlockLength = 6;
        LocalFADT.Gpe1Block = 0x00005678;
        LocalFADT.Gpe1Base = 96;

        LocalFADT.Pm1EventLength = 4;
        LocalFADT.Pm1aEventBlock = 0x00001aaa;
        LocalFADT.Pm1bEventBlock = 0x00001bbb;

        LocalFADT.Pm1ControlLength = 2;
        LocalFADT.Pm1aControlBlock = 0xB0;

        LocalFADT.PmTimerLength = 4;
        LocalFADT.PmTimerBlock = 0xA0;

        LocalFADT.Pm2ControlBlock = 0xC0;
        LocalFADT.Pm2ControlLength = 1;

        /* Setup one example X-64 field */

        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);

        /* Complete the FADT with the checksum */

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalFADT, LocalFADT.Header.Length);
    }

    /* Build a FACS */

    ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
    ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS);

    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
    LocalFACS.GlobalLock = 0x11AA0011;

    return (AE_OK);
}
Example #8
0
ACPI_STATUS
AeBuildLocalTables (
    UINT32                  TableCount,
    AE_TABLE_DESC           *TableList)
{
    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
    UINT32                  XsdtSize;
    AE_TABLE_DESC           *NextTable;
    UINT32                  NextIndex;
    ACPI_TABLE_FADT         *ExternalFadt = NULL;


    /*
     * Update the table count. For the DSDT, it is not put into the XSDT.
     * For the FADT, this table is already accounted for since we usually
     * install a local FADT.
     */
    NextTable = TableList;
    while (NextTable)
    {
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
            ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            TableCount--;
        }
        NextTable = NextTable->Next;
    }

    XsdtSize = (((TableCount + 1) * sizeof (UINT64)) + sizeof (ACPI_TABLE_HEADER));
    if (AcpiGbl_LoadTestTables)
    {
        XsdtSize += BASE_XSDT_SIZE;
    }

    /* Build an XSDT */

    LocalXSDT = AcpiOsAllocate (XsdtSize);
    if (!LocalXSDT)
    {
        return (AE_NO_MEMORY);
    }

    ACPI_MEMSET (LocalXSDT, 0, XsdtSize);
    AeInitializeTableHeader ((void *) LocalXSDT, ACPI_SIG_XSDT, XsdtSize);

    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);
    NextIndex = 1;

    /*
     * Install the user tables. The DSDT must be installed in the FADT.
     * All other tables are installed directly into the XSDT.
     *
     * Note: The tables are loaded in reverse order from the incoming
     * input, which makes it match the command line order.
     */
    NextTable = TableList;
    while (NextTable)
    {
        /*
         * Incoming DSDT or FADT are special cases. All other tables are
         * just immediately installed into the XSDT.
         */
        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
        {
            if (DsdtAddress)
            {
                printf ("Already found a DSDT, only one allowed\n");
                return (AE_ALREADY_EXISTS);
            }

            /* The incoming user table is a DSDT */

            DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            DsdtToInstallOverride = NextTable->Table;
        }
        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
        {
            ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
            LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
        }
        else
        {
            /* Install the table in the XSDT */

            LocalXSDT->TableOffsetEntry[TableCount - NextIndex + 1] =
                ACPI_PTR_TO_PHYSADDR (NextTable->Table);
            NextIndex++;
        }

        NextTable = NextTable->Next;
    }

    /* Install the optional extra local tables */

    if (AcpiGbl_LoadTestTables)
    {
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalTEST);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE);

        /* Install two SSDTs to test multiple table support */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code);

        /* Install the OEM1 table to test LoadTable */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Oem1Code);

        /* Install the OEMx table to test LoadTable */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&OemxCode);

         /* Install the ECDT table to test _REG */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&EcdtCode);

        /* Install two UEFIs to test multiple table support */

        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi1Code);
        LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi2Code);
    }

    /* Build an RSDP. Contains a valid XSDT only, no RSDT */

    ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
    ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature);
    ACPI_MEMCPY (LocalRSDP.OemId, "Intel", 6);

    LocalRSDP.Revision = 2;
    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
    LocalRSDP.Length = sizeof (ACPI_TABLE_RSDP);

    /* Set checksums for both XSDT and RSDP */

    LocalXSDT->Header.Checksum = 0;
    LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) LocalXSDT, LocalXSDT->Header.Length);

    LocalRSDP.Checksum = 0;
    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
        (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);

    if (!DsdtAddress)
    {
        /* Use the local DSDT because incoming table(s) are all SSDT(s) */

        DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode);
        DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode);
    }

    /*
     * Build an FADT. There are three options for the FADT:
     * 1) Incoming external FADT specified on the command line
     * 2) A "hardware reduced" local FADT
     * 3) A fully featured local FADT
     */
    if (ExternalFadt)
    {
        /*
         * Use the external FADT, but we must update the DSDT/FACS addresses
         * as well as the checksum
         */
        ExternalFadt->Dsdt = DsdtAddress;
        if (!AcpiGbl_ReducedHardware)
        {
            ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
        }

        /* Is there room in the FADT for the XDsdst and XFacs 64-bit pointers? */

        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
        {
            ExternalFadt->XDsdt = DsdtAddress;

            if (!AcpiGbl_ReducedHardware)
            {
                ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
            }
        }

        /* Complete the FADT with the checksum */

        ExternalFadt->Header.Checksum = 0;
        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) ExternalFadt, ExternalFadt->Header.Length);
    }
    else if (AcpiGbl_UseHwReducedFadt)
    {
        ACPI_MEMCPY (&LocalFADT, HwReducedFadtCode, sizeof (ACPI_TABLE_FADT));
        LocalFADT.Dsdt = DsdtAddress;
        LocalFADT.XDsdt = DsdtAddress;

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalFADT, LocalFADT.Header.Length);
    }
    else
    {
        /*
         * Build a local FADT so we can test the hardware/event init
         */
        ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));
        LocalFADT.Header.Revision = 5;
        AeInitializeTableHeader ((void *) &LocalFADT, ACPI_SIG_FADT, sizeof (ACPI_TABLE_FADT));

        /* Setup FADT header and DSDT/FACS addresses */

        LocalFADT.Dsdt = 0;
        LocalFADT.Facs = 0;

        LocalFADT.XDsdt = DsdtAddress;
        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);

        /* Miscellaneous FADT fields */

        LocalFADT.Gpe0BlockLength = 0x08;
        LocalFADT.Gpe0Block = 0x00001234;

        LocalFADT.Gpe1BlockLength = 0x80;
        LocalFADT.Gpe1Block = 0x00005678;
        LocalFADT.Gpe1Base = 100;

        LocalFADT.Pm1EventLength = 4;
        LocalFADT.Pm1aEventBlock = 0x00001aaa;
        LocalFADT.Pm1bEventBlock = 0x00001bbb;

        LocalFADT.Pm1ControlLength = 2;
        LocalFADT.Pm1aControlBlock = 0xB0;

        LocalFADT.PmTimerLength = 4;
        LocalFADT.PmTimerBlock = 0xA0;

        LocalFADT.Pm2ControlBlock = 0xC0;
        LocalFADT.Pm2ControlLength = 1;

        /* Setup one example X-64 GAS field */

        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);

        /* Complete the FADT with the checksum */

        LocalFADT.Header.Checksum = 0;
        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalFADT, LocalFADT.Header.Length);
    }

    /* Build a FACS */

    ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
    ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS);

    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
    LocalFACS.GlobalLock = 0x11AA0011;

    /* Build the optional local tables */

    if (AcpiGbl_LoadTestTables)
    {
        /*
         * Build a fake table [TEST] so that we make sure that the
         * ACPICA core ignores it
         */
        ACPI_MEMSET (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER));
        ACPI_MOVE_NAME (LocalTEST.Signature, "TEST");

        LocalTEST.Revision = 1;
        LocalTEST.Length = sizeof (ACPI_TABLE_HEADER);
        LocalTEST.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalTEST, LocalTEST.Length);

        /*
         * Build a fake table with a bad signature [BAD!] so that we make
         * sure that the ACPICA core ignores it
         */
        ACPI_MEMSET (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER));
        ACPI_MOVE_NAME (LocalBADTABLE.Signature, "BAD!");

        LocalBADTABLE.Revision = 1;
        LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER);
        LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum (
            (void *) &LocalBADTABLE, LocalBADTABLE.Length);
    }

    return (AE_OK);
}
Example #9
0
ACPI_STATUS
AcpiGetObjectInfo (
    ACPI_HANDLE             Handle,
    ACPI_BUFFER             *Buffer)
{
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_DEVICE_INFO        *Info;
    ACPI_DEVICE_INFO        *ReturnInfo;
    ACPI_COMPATIBLE_ID_LIST *CidList = NULL;
    ACPI_SIZE               Size;


    /* Parameter validation */

    if (!Handle || !Buffer)
    {
        return (AE_BAD_PARAMETER);
    }

    Status = AcpiUtValidateBuffer (Buffer);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_INFO));
    if (!Info)
    {
        return (AE_NO_MEMORY);
    }

    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    Node = AcpiNsMapHandleToNode (Handle);
    if (!Node)
    {
        (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
        goto Cleanup;
    }

    /* Init return structure */

    Size = sizeof (ACPI_DEVICE_INFO);

    Info->Type  = Node->Type;
    Info->Name  = Node->Name.Integer;
    Info->Valid = 0;

    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    /* If not a device, we are all done */

    if (Info->Type == ACPI_TYPE_DEVICE)
    {
        /*
         * Get extra info for ACPI Devices objects only:
         * Run the Device _HID, _UID, _CID, _STA, _ADR and _SxD methods.
         *
         * Note: none of these methods are required, so they may or may
         * not be present for this device.  The Info->Valid bitfield is used
         * to indicate which methods were found and ran successfully.
         */

        /* Execute the Device._HID method */

        Status = AcpiUtExecute_HID (Node, &Info->HardwareId);
        if (ACPI_SUCCESS (Status))
        {
            Info->Valid |= ACPI_VALID_HID;
        }

        /* Execute the Device._UID method */

        Status = AcpiUtExecute_UID (Node, &Info->UniqueId);
        if (ACPI_SUCCESS (Status))
        {
            Info->Valid |= ACPI_VALID_UID;
        }

        /* Execute the Device._CID method */

        Status = AcpiUtExecute_CID (Node, &CidList);
        if (ACPI_SUCCESS (Status))
        {
            Size += CidList->Size;
            Info->Valid |= ACPI_VALID_CID;
        }

        /* Execute the Device._STA method */

        Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
        if (ACPI_SUCCESS (Status))
        {
            Info->Valid |= ACPI_VALID_STA;
        }

        /* Execute the Device._ADR method */

        Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
                        &Info->Address);
        if (ACPI_SUCCESS (Status))
        {
            Info->Valid |= ACPI_VALID_ADR;
        }

        /* Execute the Device._SxD methods */

        Status = AcpiUtExecute_Sxds (Node, Info->HighestDstates);
        if (ACPI_SUCCESS (Status))
        {
            Info->Valid |= ACPI_VALID_SXDS;
        }
    }

    /* Validate/Allocate/Clear caller buffer */

    Status = AcpiUtInitializeBuffer (Buffer, Size);
    if (ACPI_FAILURE (Status))
    {
        goto Cleanup;
    }

    /* Populate the return buffer */

    ReturnInfo = Buffer->Pointer;
    ACPI_MEMCPY (ReturnInfo, Info, sizeof (ACPI_DEVICE_INFO));

    if (CidList)
    {
        ACPI_MEMCPY (&ReturnInfo->CompatibilityId, CidList, CidList->Size);
    }


Cleanup:
    ACPI_FREE (Info);
    if (CidList)
    {
        ACPI_FREE (CidList);
    }
    return (Status);
}
Example #10
0
ACPI_STATUS
AcpiExOpcode_2A_1T_1R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_OPERAND_OBJECT     *ReturnDesc = NULL;
    UINT64                  Index;
    ACPI_STATUS             Status = AE_OK;
    ACPI_SIZE               Length = 0;


    ACPI_FUNCTION_TRACE_STR (ExOpcode_2A_1T_1R,
        AcpiPsGetOpcodeName (WalkState->Opcode));


    /* Execute the opcode */

    if (WalkState->OpInfo->Flags & AML_MATH)
    {
        /* All simple math opcodes (add, etc.) */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        ReturnDesc->Integer.Value = AcpiExDoMathOp (WalkState->Opcode,
                                                Operand[0]->Integer.Value,
                                                Operand[1]->Integer.Value);
        goto StoreResultToTarget;
    }

    switch (WalkState->Opcode)
    {
    case AML_MOD_OP: /* Mod (Dividend, Divisor, RemainderResult (ACPI 2.0) */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* ReturnDesc will contain the remainder */

        Status = AcpiUtDivide (Operand[0]->Integer.Value,
                               Operand[1]->Integer.Value,
                               NULL,
                               &ReturnDesc->Integer.Value);
        break;

    case AML_CONCAT_OP: /* Concatenate (Data1, Data2, Result) */

        Status = AcpiExDoConcatenate (Operand[0], Operand[1],
                    &ReturnDesc, WalkState);
        break;

    case AML_TO_STRING_OP: /* ToString (Buffer, Length, Result) (ACPI 2.0) */
        /*
         * Input object is guaranteed to be a buffer at this point (it may have
         * been converted.)  Copy the raw buffer data to a new object of
         * type String.
         */

        /*
         * Get the length of the new string. It is the smallest of:
         * 1) Length of the input buffer
         * 2) Max length as specified in the ToString operator
         * 3) Length of input buffer up to a zero byte (null terminator)
         *
         * NOTE: A length of zero is ok, and will create a zero-length, null
         *       terminated string.
         */
        while ((Length < Operand[0]->Buffer.Length) &&
               (Length < Operand[1]->Integer.Value) &&
               (Operand[0]->Buffer.Pointer[Length]))
        {
            Length++;
        }

        /* Allocate a new string object */

        ReturnDesc = AcpiUtCreateStringObject (Length);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /*
         * Copy the raw buffer data with no transform.
         * (NULL terminated already)
         */
        ACPI_MEMCPY (ReturnDesc->String.Pointer,
            Operand[0]->Buffer.Pointer, Length);
        break;

    case AML_CONCAT_RES_OP:

        /* ConcatenateResTemplate (Buffer, Buffer, Result) (ACPI 2.0) */

        Status = AcpiExConcatTemplate (Operand[0], Operand[1],
                    &ReturnDesc, WalkState);
        break;

    case AML_INDEX_OP:              /* Index (Source Index Result) */

        /* Create the internal return object */

        ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE);
        if (!ReturnDesc)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Initialize the Index reference object */

        Index = Operand[1]->Integer.Value;
        ReturnDesc->Reference.Value = (UINT32) Index;
        ReturnDesc->Reference.Class = ACPI_REFCLASS_INDEX;

        /*
         * At this point, the Source operand is a String, Buffer, or Package.
         * Verify that the index is within range.
         */
        switch ((Operand[0])->Common.Type)
        {
        case ACPI_TYPE_STRING:

            if (Index >= Operand[0]->String.Length)
            {
                Length = Operand[0]->String.Length;
                Status = AE_AML_STRING_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
            break;

        case ACPI_TYPE_BUFFER:

            if (Index >= Operand[0]->Buffer.Length)
            {
                Length = Operand[0]->Buffer.Length;
                Status = AE_AML_BUFFER_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD;
            break;

        case ACPI_TYPE_PACKAGE:

            if (Index >= Operand[0]->Package.Count)
            {
                Length = Operand[0]->Package.Count;
                Status = AE_AML_PACKAGE_LIMIT;
            }

            ReturnDesc->Reference.TargetType = ACPI_TYPE_PACKAGE;
            ReturnDesc->Reference.Where = &Operand[0]->Package.Elements [Index];
            break;

        default:

            Status = AE_AML_INTERNAL;
            goto Cleanup;
        }

        /* Failure means that the Index was beyond the end of the object */

        if (ACPI_FAILURE (Status))
        {
            ACPI_EXCEPTION ((AE_INFO, Status,
                "Index (0x%X%8.8X) is beyond end of object (length 0x%X)",
                ACPI_FORMAT_UINT64 (Index), (UINT32) Length));
            goto Cleanup;
        }

        /*
         * Save the target object and add a reference to it for the life
         * of the index
         */
        ReturnDesc->Reference.Object = Operand[0];
        AcpiUtAddReference (Operand[0]);

        /* Store the reference to the Target */

        Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);

        /* Return the reference */

        WalkState->ResultObj = ReturnDesc;
        goto Cleanup;

    default:

        ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
            WalkState->Opcode));
        Status = AE_AML_BAD_OPCODE;
        break;
    }


StoreResultToTarget:

    if (ACPI_SUCCESS (Status))
    {
        /*
         * Store the result of the operation (which is now in ReturnDesc) into
         * the Target descriptor.
         */
        Status = AcpiExStore (ReturnDesc, Operand[2], WalkState);
        if (ACPI_FAILURE (Status))
        {
            goto Cleanup;
        }

        if (!WalkState->ResultObj)
        {
            WalkState->ResultObj = ReturnDesc;
        }
    }


Cleanup:

    /* Delete return object on error */

    if (ACPI_FAILURE (Status))
    {
        AcpiUtRemoveReference (ReturnDesc);
        WalkState->ResultObj = NULL;
    }

    return_ACPI_STATUS (Status);
}
Example #11
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_ex_store_buffer_to_buffer
 *
 * PARAMETERS:  source_desc         - Source object to copy
 *              target_desc         - Destination object of the copy
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Copy a buffer object to another buffer object.
 *
 ******************************************************************************/
acpi_status
acpi_ex_store_buffer_to_buffer(union acpi_operand_object *source_desc,
			       union acpi_operand_object *target_desc)
{
	u32 length;
	u8 *buffer;

	ACPI_FUNCTION_TRACE_PTR(ex_store_buffer_to_buffer, source_desc);

	if (source_desc == target_desc) {
		return_ACPI_STATUS(AE_OK);
	}

	/* We know that source_desc is a buffer by now */

	buffer = ACPI_CAST_PTR(u8, source_desc->buffer.pointer);
	length = source_desc->buffer.length;

	/*
	 * If target is a buffer of length zero or is a static buffer,
	 * allocate a new buffer of the proper length
	 */
	if ((target_desc->buffer.length == 0) ||
	    (target_desc->common.flags & AOPOBJ_STATIC_POINTER)) {
		target_desc->buffer.pointer = ACPI_ALLOCATE(length);
		if (!target_desc->buffer.pointer) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		target_desc->buffer.length = length;
	}

	/* Copy source buffer to target buffer */

	if (length <= target_desc->buffer.length) {

		/* Clear existing buffer and copy in the new one */

		ACPI_MEMSET(target_desc->buffer.pointer, 0,
			    target_desc->buffer.length);
		ACPI_MEMCPY(target_desc->buffer.pointer, buffer, length);

#ifdef ACPI_OBSOLETE_BEHAVIOR
		/*
		 * NOTE: ACPI versions up to 3.0 specified that the buffer must be
		 * truncated if the string is smaller than the buffer.  However, "other"
		 * implementations of ACPI never did this and thus became the defacto
		 * standard. ACPI 3.0_a changes this behavior such that the buffer
		 * is no longer truncated.
		 */

		/*
		 * OBSOLETE BEHAVIOR:
		 * If the original source was a string, we must truncate the buffer,
		 * according to the ACPI spec.  Integer-to-Buffer and Buffer-to-Buffer
		 * copy must not truncate the original buffer.
		 */
		if (original_src_type == ACPI_TYPE_STRING) {

			/* Set the new length of the target */

			target_desc->buffer.length = length;
		}
#endif
	} else {
		/* Truncate the source, copy only what will fit */

		ACPI_MEMCPY(target_desc->buffer.pointer, buffer,
			    target_desc->buffer.length);

		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
				  "Truncating source buffer from %X to %X\n",
				  length, target_desc->buffer.length));
	}

	/* Copy flags */

	target_desc->buffer.flags = source_desc->buffer.flags;
	target_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
	return_ACPI_STATUS(AE_OK);
}
acpi_status
acpi_get_table (
    acpi_table_type                 table_type,
    u32                             instance,
    struct acpi_buffer              *ret_buffer)
{
    struct acpi_table_header        *tbl_ptr;
    acpi_status                     status;
    acpi_size                       table_length;


    ACPI_FUNCTION_TRACE ("acpi_get_table");


    /* Parameter validation */

    if (instance == 0) {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }

    status = acpi_ut_validate_buffer (ret_buffer);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Check the table type and instance */

    if ((table_type > ACPI_TABLE_MAX)   ||
            (ACPI_IS_SINGLE_TABLE (acpi_gbl_table_data[table_type].flags) &&
             instance > 1)) {
        return_ACPI_STATUS (AE_BAD_PARAMETER);
    }


    /* Get a pointer to the entire table */

    status = acpi_tb_get_table_ptr (table_type, instance, &tbl_ptr);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /*
     * acpi_tb_get_table_ptr will return a NULL pointer if the
     * table is not loaded.
     */
    if (tbl_ptr == NULL) {
        return_ACPI_STATUS (AE_NOT_EXIST);
    }

    /* Get the table length */

    if (table_type == ACPI_TABLE_RSDP) {
        /*
         *  RSD PTR is the only "table" without a header
         */
        table_length = sizeof (struct rsdp_descriptor);
    }
    else {
        table_length = (acpi_size) tbl_ptr->length;
    }

    /* Validate/Allocate/Clear caller buffer */

    status = acpi_ut_initialize_buffer (ret_buffer, table_length);
    if (ACPI_FAILURE (status)) {
        return_ACPI_STATUS (status);
    }

    /* Copy the table to the buffer */

    ACPI_MEMCPY ((void *) ret_buffer->pointer, (void *) tbl_ptr, table_length);
    return_ACPI_STATUS (AE_OK);
}
Example #13
0
ACPI_STATUS
AcpiDsBuildInternalBufferObj (
    ACPI_WALK_STATE         *WalkState,
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  BufferLength,
    ACPI_OPERAND_OBJECT     **ObjDescPtr)
{
    ACPI_PARSE_OBJECT       *Arg;
    ACPI_OPERAND_OBJECT     *ObjDesc;
    ACPI_PARSE_OBJECT       *ByteList;
    UINT32                  ByteListLength = 0;


    ACPI_FUNCTION_TRACE (DsBuildInternalBufferObj);


    /*
     * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
     * The buffer object already exists (from the NS node), otherwise it must
     * be created.
     */
    ObjDesc = *ObjDescPtr;
    if (!ObjDesc)
    {
        /* Create a new buffer object */

        ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_BUFFER);
        *ObjDescPtr = ObjDesc;
        if (!ObjDesc)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }
    }

    /*
     * Second arg is the buffer data (optional) ByteList can be either
     * individual bytes or a string initializer.  In either case, a
     * ByteList appears in the AML.
     */
    Arg = Op->Common.Value.Arg;         /* skip first arg */

    ByteList = Arg->Named.Next;
    if (ByteList)
    {
        if (ByteList->Common.AmlOpcode != AML_INT_BYTELIST_OP)
        {
            ACPI_ERROR ((AE_INFO,
                "Expecting bytelist, found AML opcode 0x%X in op %p",
                ByteList->Common.AmlOpcode, ByteList));

            AcpiUtRemoveReference (ObjDesc);
            return (AE_TYPE);
        }

        ByteListLength = (UINT32) ByteList->Common.Value.Integer;
    }

    /*
     * The buffer length (number of bytes) will be the larger of:
     * 1) The specified buffer length and
     * 2) The length of the initializer byte list
     */
    ObjDesc->Buffer.Length = BufferLength;
    if (ByteListLength > BufferLength)
    {
        ObjDesc->Buffer.Length = ByteListLength;
    }

    /* Allocate the buffer */

    if (ObjDesc->Buffer.Length == 0)
    {
        ObjDesc->Buffer.Pointer = NULL;
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
            "Buffer defined with zero length in AML, creating\n"));
    }
    else
    {
        ObjDesc->Buffer.Pointer = ACPI_ALLOCATE_ZEROED (
                                        ObjDesc->Buffer.Length);
        if (!ObjDesc->Buffer.Pointer)
        {
            AcpiUtDeleteObjectDesc (ObjDesc);
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        /* Initialize buffer from the ByteList (if present) */

        if (ByteList)
        {
            ACPI_MEMCPY (ObjDesc->Buffer.Pointer, ByteList->Named.Data,
                         ByteListLength);
        }
    }

    ObjDesc->Buffer.Flags |= AOPOBJ_DATA_VALID;
    Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc);
    return_ACPI_STATUS (AE_OK);
}
Example #14
0
acpi_status
acpi_get_object_info (
	acpi_handle                     handle,
	struct acpi_buffer              *buffer)
{
	acpi_status                     status;
	struct acpi_namespace_node      *node;
	struct acpi_device_info         info;
	struct acpi_device_info         *return_info;
	struct acpi_compatible_id_list *cid_list = NULL;
	acpi_size                       size;


	/* Parameter validation */

	if (!handle || !buffer) {
		return (AE_BAD_PARAMETER);
	}

	status = acpi_ut_validate_buffer (buffer);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	node = acpi_ns_map_handle_to_node (handle);
	if (!node) {
		(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
		return (AE_BAD_PARAMETER);
	}

	/* Init return structure */

	size = sizeof (struct acpi_device_info);
	ACPI_MEMSET (&info, 0, size);

	info.type  = node->type;
	info.name  = node->name.integer;
	info.valid = 0;

	status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
	if (ACPI_FAILURE (status)) {
		return (status);
	}

	/* If not a device, we are all done */

	if (info.type == ACPI_TYPE_DEVICE) {
		/*
		 * Get extra info for ACPI Devices objects only:
		 * Run the Device _HID, _UID, _CID, _STA, and _ADR methods.
		 *
		 * Note: none of these methods are required, so they may or may
		 * not be present for this device.  The Info.Valid bitfield is used
		 * to indicate which methods were found and ran successfully.
		 */

		/* Execute the Device._HID method */

		status = acpi_ut_execute_HID (node, &info.hardware_id);
		if (ACPI_SUCCESS (status)) {
			info.valid |= ACPI_VALID_HID;
		}

		/* Execute the Device._UID method */

		status = acpi_ut_execute_UID (node, &info.unique_id);
		if (ACPI_SUCCESS (status)) {
			info.valid |= ACPI_VALID_UID;
		}

		/* Execute the Device._CID method */

		status = acpi_ut_execute_CID (node, &cid_list);
		if (ACPI_SUCCESS (status)) {
			size += ((acpi_size) cid_list->count - 1) *
					 sizeof (struct acpi_compatible_id);
			info.valid |= ACPI_VALID_CID;
		}

		/* Execute the Device._STA method */

		status = acpi_ut_execute_STA (node, &info.current_status);
		if (ACPI_SUCCESS (status)) {
			info.valid |= ACPI_VALID_STA;
		}

		/* Execute the Device._ADR method */

		status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
				  &info.address);
		if (ACPI_SUCCESS (status)) {
			info.valid |= ACPI_VALID_ADR;
		}

		/* Execute the Device._sx_d methods */

		status = acpi_ut_execute_sxds (node, info.highest_dstates);
		if (ACPI_SUCCESS (status)) {
			info.valid |= ACPI_VALID_STA;
		}

		status = AE_OK;
	}

	/* Validate/Allocate/Clear caller buffer */

	status = acpi_ut_initialize_buffer (buffer, size);
	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}

	/* Populate the return buffer */

	return_info = buffer->pointer;
	ACPI_MEMCPY (return_info, &info, sizeof (struct acpi_device_info));

	if (cid_list) {
		ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
	}


cleanup:
	if (cid_list) {
		ACPI_MEM_FREE (cid_list);
	}
	return (status);
}
Example #15
0
static void ACPI_SYSTEM_XFACE acpi_ev_asynch_execute_gpe_method(void *context)
{
    struct acpi_gpe_event_info *gpe_event_info = (void *)context;
    acpi_status status;
    struct acpi_gpe_event_info local_gpe_event_info;
    struct acpi_evaluate_info *info;

    ACPI_FUNCTION_TRACE(ev_asynch_execute_gpe_method);

    status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
    if (ACPI_FAILURE(status)) {
        return_VOID;
    }

    /* Must revalidate the gpe_number/gpe_block */

    if (!acpi_ev_valid_gpe_event(gpe_event_info)) {
        status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
        return_VOID;
    }

    /* Set the GPE flags for return to enabled state */

    (void)acpi_ev_enable_gpe(gpe_event_info, FALSE);

    /*
     * Take a snapshot of the GPE info for this level - we copy the info to
     * prevent a race condition with remove_handler/remove_block.
     */
    ACPI_MEMCPY(&local_gpe_event_info, gpe_event_info,
                sizeof(struct acpi_gpe_event_info));

    status = acpi_ut_release_mutex(ACPI_MTX_EVENTS);
    if (ACPI_FAILURE(status)) {
        return_VOID;
    }

    /*
     * Must check for control method type dispatch one more time to avoid a
     * race with ev_gpe_install_handler
     */
    if ((local_gpe_event_info.flags & ACPI_GPE_DISPATCH_MASK) ==
            ACPI_GPE_DISPATCH_METHOD) {

        /* Allocate the evaluation information block */

        info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
        if (!info) {
            status = AE_NO_MEMORY;
        } else {
            /*
             * Invoke the GPE Method (_Lxx, _Exx) i.e., evaluate the _Lxx/_Exx
             * control method that corresponds to this GPE
             */
            info->prefix_node =
                local_gpe_event_info.dispatch.method_node;
            info->flags = ACPI_IGNORE_RETURN_VALUE;

            status = acpi_ns_evaluate(info);
            ACPI_FREE(info);
        }

        if (ACPI_FAILURE(status)) {
            ACPI_EXCEPTION((AE_INFO, status,
                            "while evaluating GPE method [%4.4s]",
                            acpi_ut_get_node_name
                            (local_gpe_event_info.dispatch.
                             method_node)));
        }
    }
    /* Defer enabling of GPE until all notify handlers are done */
    acpi_os_execute(OSL_NOTIFY_HANDLER, acpi_ev_asynch_enable_gpe,
                    gpe_event_info);
    return_VOID;
}
Example #16
0
static acpi_status
acpi_ex_field_datum_io(union acpi_operand_object *obj_desc,
		       u32 field_datum_byte_offset,
		       acpi_integer * value, u32 read_write)
{
	acpi_status status;
	acpi_integer local_value;

	ACPI_FUNCTION_TRACE_U32(ex_field_datum_io, field_datum_byte_offset);

	if (read_write == ACPI_READ) {
		if (!value) {
			local_value = 0;

			/* To support reads without saving return value */
			value = &local_value;
		}

		/* Clear the entire return buffer first, [Very Important!] */

		*value = 0;
	}

	/*
	 * The four types of fields are:
	 *
	 * buffer_field - Read/write from/to a Buffer
	 * region_field - Read/write from/to a Operation Region.
	 * bank_field  - Write to a Bank Register, then read/write from/to an
	 *               operation_region
	 * index_field - Write to an Index Register, then read/write from/to a
	 *               Data Register
	 */
	switch (ACPI_GET_OBJECT_TYPE(obj_desc)) {
	case ACPI_TYPE_BUFFER_FIELD:
		/*
		 * If the buffer_field arguments have not been previously evaluated,
		 * evaluate them now and save the results.
		 */
		if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) {
			status = acpi_ds_get_buffer_field_arguments(obj_desc);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}

		if (read_write == ACPI_READ) {
			/*
			 * Copy the data from the source buffer.
			 * Length is the field width in bytes.
			 */
			ACPI_MEMCPY(value,
				    (obj_desc->buffer_field.buffer_obj)->buffer.
				    pointer +
				    obj_desc->buffer_field.base_byte_offset +
				    field_datum_byte_offset,
				    obj_desc->common_field.access_byte_width);
		} else {
			/*
			 * Copy the data to the target buffer.
			 * Length is the field width in bytes.
			 */
			ACPI_MEMCPY((obj_desc->buffer_field.buffer_obj)->buffer.
				    pointer +
				    obj_desc->buffer_field.base_byte_offset +
				    field_datum_byte_offset, value,
				    obj_desc->common_field.access_byte_width);
		}

		status = AE_OK;
		break;

	case ACPI_TYPE_LOCAL_BANK_FIELD:

		/*
		 * Ensure that the bank_value is not beyond the capacity of
		 * the register
		 */
		if (acpi_ex_register_overflow(obj_desc->bank_field.bank_obj,
					      (acpi_integer) obj_desc->
					      bank_field.value)) {
			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
		}

		/*
		 * For bank_fields, we must write the bank_value to the bank_register
		 * (itself a region_field) before we can access the data.
		 */
		status =
		    acpi_ex_insert_into_field(obj_desc->bank_field.bank_obj,
					      &obj_desc->bank_field.value,
					      sizeof(obj_desc->bank_field.
						     value));
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/*
		 * Now that the Bank has been selected, fall through to the
		 * region_field case and write the datum to the Operation Region
		 */

		/*lint -fallthrough */

	case ACPI_TYPE_LOCAL_REGION_FIELD:
		/*
		 * For simple region_fields, we just directly access the owning
		 * Operation Region.
		 */
		status =
		    acpi_ex_access_region(obj_desc, field_datum_byte_offset,
					  value, read_write);
		break;

	case ACPI_TYPE_LOCAL_INDEX_FIELD:

		/*
		 * Ensure that the index_value is not beyond the capacity of
		 * the register
		 */
		if (acpi_ex_register_overflow(obj_desc->index_field.index_obj,
					      (acpi_integer) obj_desc->
					      index_field.value)) {
			return_ACPI_STATUS(AE_AML_REGISTER_LIMIT);
		}

		/* Write the index value to the index_register (itself a region_field) */

		field_datum_byte_offset += obj_desc->index_field.value;

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "Write to Index Register: Value %8.8X\n",
				  field_datum_byte_offset));

		status =
		    acpi_ex_insert_into_field(obj_desc->index_field.index_obj,
					      &field_datum_byte_offset,
					      sizeof(field_datum_byte_offset));
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
				  "I/O to Data Register: ValuePtr %p\n",
				  value));

		if (read_write == ACPI_READ) {

			/* Read the datum from the data_register */

			status =
			    acpi_ex_extract_from_field(obj_desc->index_field.
						       data_obj, value,
						       sizeof(acpi_integer));
		} else {
			/* Write the datum to the data_register */

			status =
			    acpi_ex_insert_into_field(obj_desc->index_field.
						      data_obj, value,
						      sizeof(acpi_integer));
		}
		break;

	default:

		ACPI_ERROR((AE_INFO, "Wrong object type in field I/O %X",
			    ACPI_GET_OBJECT_TYPE(obj_desc)));
		status = AE_AML_INTERNAL;
		break;
	}

	if (ACPI_SUCCESS(status)) {
		if (read_write == ACPI_READ) {
			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
					  "Value Read %8.8X%8.8X, Width %d\n",
					  ACPI_FORMAT_UINT64(*value),
					  obj_desc->common_field.
					  access_byte_width));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
					  "Value Written %8.8X%8.8X, Width %d\n",
					  ACPI_FORMAT_UINT64(*value),
					  obj_desc->common_field.
					  access_byte_width));
		}
	}

	return_ACPI_STATUS(status);
}
Example #17
0
static ACPI_STATUS
AcpiUtCopyIsimpleToEsimple (
    ACPI_OPERAND_OBJECT     *InternalObject,
    ACPI_OBJECT             *ExternalObject,
    UINT8                   *DataSpace,
    ACPI_SIZE               *BufferSpaceUsed)
{
    ACPI_STATUS             Status = AE_OK;


    ACPI_FUNCTION_TRACE (UtCopyIsimpleToEsimple);


    *BufferSpaceUsed = 0;

    /*
     * Check for NULL object case (could be an uninitialized
     * package element)
     */
    if (!InternalObject)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* Always clear the external object */

    ACPI_MEMSET (ExternalObject, 0, sizeof (ACPI_OBJECT));

    /*
     * In general, the external object will be the same type as
     * the internal object
     */
    ExternalObject->Type = InternalObject->Common.Type;

    /* However, only a limited number of external types are supported */

    switch (InternalObject->Common.Type)
    {
    case ACPI_TYPE_STRING:

        ExternalObject->String.Pointer = (char *) DataSpace;
        ExternalObject->String.Length  = InternalObject->String.Length;
        *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
                               (ACPI_SIZE) InternalObject->String.Length + 1);

        ACPI_MEMCPY ((void *) DataSpace,
                     (void *) InternalObject->String.Pointer,
                     (ACPI_SIZE) InternalObject->String.Length + 1);
        break;


    case ACPI_TYPE_BUFFER:

        ExternalObject->Buffer.Pointer = DataSpace;
        ExternalObject->Buffer.Length  = InternalObject->Buffer.Length;
        *BufferSpaceUsed = ACPI_ROUND_UP_TO_NATIVE_WORD (
                               InternalObject->String.Length);

        ACPI_MEMCPY ((void *) DataSpace,
                     (void *) InternalObject->Buffer.Pointer,
                     InternalObject->Buffer.Length);
        break;


    case ACPI_TYPE_INTEGER:

        ExternalObject->Integer.Value = InternalObject->Integer.Value;
        break;


    case ACPI_TYPE_LOCAL_REFERENCE:

        /* This is an object reference. */

        switch (InternalObject->Reference.Class)
        {
        case ACPI_REFCLASS_NAME:

            /*
             * For namepath, return the object handle ("reference")
             * We are referring to the namespace node
             */
            ExternalObject->Reference.Handle =
                InternalObject->Reference.Node;
            ExternalObject->Reference.ActualType =
                AcpiNsGetType (InternalObject->Reference.Node);
            break;

        default:

            /* All other reference types are unsupported */

            return_ACPI_STATUS (AE_TYPE);
        }
        break;


    case ACPI_TYPE_PROCESSOR:

        ExternalObject->Processor.ProcId =
            InternalObject->Processor.ProcId;
        ExternalObject->Processor.PblkAddress =
            InternalObject->Processor.Address;
        ExternalObject->Processor.PblkLength =
            InternalObject->Processor.Length;
        break;


    case ACPI_TYPE_POWER:

        ExternalObject->PowerResource.SystemLevel =
            InternalObject->PowerResource.SystemLevel;

        ExternalObject->PowerResource.ResourceOrder =
            InternalObject->PowerResource.ResourceOrder;
        break;


    default:
        /*
         * There is no corresponding external object type
         */
        ACPI_ERROR ((AE_INFO,
                     "Unsupported object type, cannot convert to external object: %s",
                     AcpiUtGetTypeName (InternalObject->Common.Type)));

        return_ACPI_STATUS (AE_SUPPORT);
    }

    return_ACPI_STATUS (Status);
}
Example #18
0
acpi_status
acpi_ex_extract_from_field(union acpi_operand_object *obj_desc,
			   void *buffer, u32 buffer_length)
{
	acpi_status status;
	acpi_integer raw_datum;
	acpi_integer merged_datum;
	u32 field_offset = 0;
	u32 buffer_offset = 0;
	u32 buffer_tail_bits;
	u32 datum_count;
	u32 field_datum_count;
	u32 i;

	ACPI_FUNCTION_TRACE(ex_extract_from_field);

	/* Validate target buffer and clear it */

	if (buffer_length <
	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) {
		ACPI_ERROR((AE_INFO,
			    "Field size %X (bits) is too large for buffer (%X)",
			    obj_desc->common_field.bit_length, buffer_length));

		return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
	}
	ACPI_MEMSET(buffer, 0, buffer_length);

	/* Compute the number of datums (access width data items) */

	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
				       obj_desc->common_field.access_bit_width);
	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
					     obj_desc->common_field.
					     start_field_bit_offset,
					     obj_desc->common_field.
					     access_bit_width);

	/* Priming read from the field */

	status =
	    acpi_ex_field_datum_io(obj_desc, field_offset, &raw_datum,
				   ACPI_READ);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}
	merged_datum =
	    raw_datum >> obj_desc->common_field.start_field_bit_offset;

	/* Read the rest of the field */

	for (i = 1; i < field_datum_count; i++) {

		/* Get next input datum from the field */

		field_offset += obj_desc->common_field.access_byte_width;
		status = acpi_ex_field_datum_io(obj_desc, field_offset,
						&raw_datum, ACPI_READ);
		if (ACPI_FAILURE(status)) {
			return_ACPI_STATUS(status);
		}

		/*
		 * Merge with previous datum if necessary.
		 *
		 * Note: Before the shift, check if the shift value will be larger than
		 * the integer size. If so, there is no need to perform the operation.
		 * This avoids the differences in behavior between different compilers
		 * concerning shift values larger than the target data width.
		 */
		if ((obj_desc->common_field.access_bit_width -
		     obj_desc->common_field.start_field_bit_offset) <
		    ACPI_INTEGER_BIT_SIZE) {
			merged_datum |=
			    raw_datum << (obj_desc->common_field.
					  access_bit_width -
					  obj_desc->common_field.
					  start_field_bit_offset);
		}

		if (i == datum_count) {
			break;
		}

		/* Write merged datum to target buffer */

		ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
			    ACPI_MIN(obj_desc->common_field.access_byte_width,
				     buffer_length - buffer_offset));

		buffer_offset += obj_desc->common_field.access_byte_width;
		merged_datum =
		    raw_datum >> obj_desc->common_field.start_field_bit_offset;
	}

	/* Mask off any extra bits in the last datum */

	buffer_tail_bits = obj_desc->common_field.bit_length %
	    obj_desc->common_field.access_bit_width;
	if (buffer_tail_bits) {
		merged_datum &= ACPI_MASK_BITS_ABOVE(buffer_tail_bits);
	}

	/* Write the last datum to the buffer */

	ACPI_MEMCPY(((char *)buffer) + buffer_offset, &merged_datum,
		    ACPI_MIN(obj_desc->common_field.access_byte_width,
			     buffer_length - buffer_offset));

	return_ACPI_STATUS(AE_OK);
}
Example #19
0
static ACPI_STATUS
AcpiUtCopySimpleObject (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *DestDesc)
{
    UINT16                  ReferenceCount;
    ACPI_OPERAND_OBJECT     *NextObject;
    ACPI_STATUS             Status;
    ACPI_SIZE               CopySize;


    /* Save fields from destination that we don't want to overwrite */

    ReferenceCount = DestDesc->Common.ReferenceCount;
    NextObject = DestDesc->Common.NextObject;

    /*
     * Copy the entire source object over the destination object.
     * Note: Source can be either an operand object or namespace node.
     */
    CopySize = sizeof (ACPI_OPERAND_OBJECT);
    if (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_NAMED)
    {
        CopySize = sizeof (ACPI_NAMESPACE_NODE);
    }

    ACPI_MEMCPY (ACPI_CAST_PTR (char, DestDesc),
                 ACPI_CAST_PTR (char, SourceDesc), CopySize);

    /* Restore the saved fields */

    DestDesc->Common.ReferenceCount = ReferenceCount;
    DestDesc->Common.NextObject = NextObject;

    /* New object is not static, regardless of source */

    DestDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;

    /* Handle the objects with extra data */

    switch (DestDesc->Common.Type)
    {
    case ACPI_TYPE_BUFFER:
        /*
         * Allocate and copy the actual buffer if and only if:
         * 1) There is a valid buffer pointer
         * 2) The buffer has a length > 0
         */
        if ((SourceDesc->Buffer.Pointer) &&
                (SourceDesc->Buffer.Length))
        {
            DestDesc->Buffer.Pointer =
                ACPI_ALLOCATE (SourceDesc->Buffer.Length);
            if (!DestDesc->Buffer.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual buffer data */

            ACPI_MEMCPY (DestDesc->Buffer.Pointer,
                         SourceDesc->Buffer.Pointer, SourceDesc->Buffer.Length);
        }
        break;

    case ACPI_TYPE_STRING:
        /*
         * Allocate and copy the actual string if and only if:
         * 1) There is a valid string pointer
         * (Pointer to a NULL string is allowed)
         */
        if (SourceDesc->String.Pointer)
        {
            DestDesc->String.Pointer =
                ACPI_ALLOCATE ((ACPI_SIZE) SourceDesc->String.Length + 1);
            if (!DestDesc->String.Pointer)
            {
                return (AE_NO_MEMORY);
            }

            /* Copy the actual string data */

            ACPI_MEMCPY (DestDesc->String.Pointer, SourceDesc->String.Pointer,
                         (ACPI_SIZE) SourceDesc->String.Length + 1);
        }
        break;

    case ACPI_TYPE_LOCAL_REFERENCE:
        /*
         * We copied the reference object, so we now must add a reference
         * to the object pointed to by the reference
         *
         * DDBHandle reference (from Load/LoadTable) is a special reference,
         * it does not have a Reference.Object, so does not need to
         * increase the reference count
         */
        if (SourceDesc->Reference.Class == ACPI_REFCLASS_TABLE)
        {
            break;
        }

        AcpiUtAddReference (SourceDesc->Reference.Object);
        break;

    case ACPI_TYPE_REGION:
        /*
         * We copied the Region Handler, so we now must add a reference
         */
        if (DestDesc->Region.Handler)
        {
            AcpiUtAddReference (DestDesc->Region.Handler);
        }
        break;

    /*
     * For Mutex and Event objects, we cannot simply copy the underlying
     * OS object. We must create a new one.
     */
    case ACPI_TYPE_MUTEX:

        Status = AcpiOsCreateMutex (&DestDesc->Mutex.OsMutex);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        break;

    case ACPI_TYPE_EVENT:

        Status = AcpiOsCreateSemaphore (ACPI_NO_UNIT_LIMIT, 0,
                                        &DestDesc->Event.OsSemaphore);
        if (ACPI_FAILURE (Status))
        {
            return (Status);
        }
        break;

    default:
        /* Nothing to do for other simple objects */
        break;
    }

    return (AE_OK);
}
Example #20
0
acpi_status
acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
			  void *buffer, u32 buffer_length)
{
	acpi_status status;
	acpi_integer mask;
	acpi_integer width_mask;
	acpi_integer merged_datum;
	acpi_integer raw_datum = 0;
	u32 field_offset = 0;
	u32 buffer_offset = 0;
	u32 buffer_tail_bits;
	u32 datum_count;
	u32 field_datum_count;
	u32 i;
	u32 required_length;
	void *new_buffer;

	ACPI_FUNCTION_TRACE(ex_insert_into_field);

	/* Validate input buffer */

	new_buffer = NULL;
	required_length =
	    ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
	/*
	 * We must have a buffer that is at least as long as the field
	 * we are writing to.  This is because individual fields are
	 * indivisible and partial writes are not supported -- as per
	 * the ACPI specification.
	 */
	if (buffer_length < required_length) {

		/* We need to create a new buffer */

		new_buffer = ACPI_ALLOCATE_ZEROED(required_length);
		if (!new_buffer) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/*
		 * Copy the original data to the new buffer, starting
		 * at Byte zero.  All unused (upper) bytes of the
		 * buffer will be 0.
		 */
		ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length);
		buffer = new_buffer;
		buffer_length = required_length;
	}

	/*
	 * Create the bitmasks used for bit insertion.
	 * Note: This if/else is used to bypass compiler differences with the
	 * shift operator
	 */
	if (obj_desc->common_field.access_bit_width == ACPI_INTEGER_BIT_SIZE) {
		width_mask = ACPI_INTEGER_MAX;
	} else {
		width_mask =
		    ACPI_MASK_BITS_ABOVE(obj_desc->common_field.
					 access_bit_width);
	}

	mask = width_mask &
	    ACPI_MASK_BITS_BELOW(obj_desc->common_field.start_field_bit_offset);

	/* Compute the number of datums (access width data items) */

	datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length,
				       obj_desc->common_field.access_bit_width);

	field_datum_count = ACPI_ROUND_UP_TO(obj_desc->common_field.bit_length +
					     obj_desc->common_field.
					     start_field_bit_offset,
					     obj_desc->common_field.
					     access_bit_width);

	/* Get initial Datum from the input buffer */

	ACPI_MEMCPY(&raw_datum, buffer,
		    ACPI_MIN(obj_desc->common_field.access_byte_width,
			     buffer_length - buffer_offset));

	merged_datum =
	    raw_datum << obj_desc->common_field.start_field_bit_offset;

	/* Write the entire field */

	for (i = 1; i < field_datum_count; i++) {

		/* Write merged datum to the target field */

		merged_datum &= mask;
		status = acpi_ex_write_with_update_rule(obj_desc, mask,
							merged_datum,
							field_offset);
		if (ACPI_FAILURE(status)) {
			goto exit;
		}

		field_offset += obj_desc->common_field.access_byte_width;

		/*
		 * Start new output datum by merging with previous input datum
		 * if necessary.
		 *
		 * Note: Before the shift, check if the shift value will be larger than
		 * the integer size. If so, there is no need to perform the operation.
		 * This avoids the differences in behavior between different compilers
		 * concerning shift values larger than the target data width.
		 */
		if ((obj_desc->common_field.access_bit_width -
		     obj_desc->common_field.start_field_bit_offset) <
		    ACPI_INTEGER_BIT_SIZE) {
			merged_datum =
			    raw_datum >> (obj_desc->common_field.
					  access_bit_width -
					  obj_desc->common_field.
					  start_field_bit_offset);
		} else {
Example #21
0
void
AcpiRsMoveData (
    void                    *Destination,
    void                    *Source,
    UINT16                  ItemCount,
    UINT8                   MoveType)
{
    UINT32                  i;


    ACPI_FUNCTION_ENTRY ();


    /* One move per item */

    for (i = 0; i < ItemCount; i++)
    {
        switch (MoveType)
        {
        /*
         * For the 8-bit case, we can perform the move all at once
         * since there are no alignment or endian issues
         */
        case ACPI_RSC_MOVE8:
        case ACPI_RSC_MOVE_GPIO_RES:
        case ACPI_RSC_MOVE_SERIAL_VEN:
        case ACPI_RSC_MOVE_SERIAL_RES:

            ACPI_MEMCPY (Destination, Source, ItemCount);
            return;

        /*
         * 16-, 32-, and 64-bit cases must use the move macros that perform
         * endian conversion and/or accommodate hardware that cannot perform
         * misaligned memory transfers
         */
        case ACPI_RSC_MOVE16:
        case ACPI_RSC_MOVE_GPIO_PIN:

            ACPI_MOVE_16_TO_16 (&ACPI_CAST_PTR (UINT16, Destination)[i],
                                &ACPI_CAST_PTR (UINT16, Source)[i]);
            break;

        case ACPI_RSC_MOVE32:

            ACPI_MOVE_32_TO_32 (&ACPI_CAST_PTR (UINT32, Destination)[i],
                                &ACPI_CAST_PTR (UINT32, Source)[i]);
            break;

        case ACPI_RSC_MOVE64:

            ACPI_MOVE_64_TO_64 (&ACPI_CAST_PTR (UINT64, Destination)[i],
                                &ACPI_CAST_PTR (UINT64, Source)[i]);
            break;

        default:

            return;
        }
    }
}
acpi_status
acpi_ex_convert_to_buffer(union acpi_operand_object *obj_desc,
			  union acpi_operand_object **result_desc)
{
	union acpi_operand_object *return_desc;
	u8 *new_buf;

	ACPI_FUNCTION_TRACE_PTR(ex_convert_to_buffer, obj_desc);

	switch (obj_desc->common.type) {
	case ACPI_TYPE_BUFFER:

		/* No conversion necessary */

		*result_desc = obj_desc;
		return_ACPI_STATUS(AE_OK);

	case ACPI_TYPE_INTEGER:

		/*
		 * Create a new Buffer object.
		 * Need enough space for one integer
		 */
		return_desc =
		    acpi_ut_create_buffer_object(acpi_gbl_integer_byte_width);
		if (!return_desc) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/* Copy the integer to the buffer, LSB first */

		new_buf = return_desc->buffer.pointer;
		ACPI_MEMCPY(new_buf,
			    &obj_desc->integer.value,
			    acpi_gbl_integer_byte_width);
		break;

	case ACPI_TYPE_STRING:

		/*
		 * Create a new Buffer object
		 * Size will be the string length
		 *
		 * NOTE: Add one to the string length to include the null terminator.
		 * The ACPI spec is unclear on this subject, but there is existing
		 * ASL/AML code that depends on the null being transferred to the new
		 * buffer.
		 */
		return_desc = acpi_ut_create_buffer_object((acpi_size)
							   obj_desc->string.
							   length + 1);
		if (!return_desc) {
			return_ACPI_STATUS(AE_NO_MEMORY);
		}

		/* Copy the string to the buffer */

		new_buf = return_desc->buffer.pointer;
		ACPI_STRNCPY((char *)new_buf, (char *)obj_desc->string.pointer,
			     obj_desc->string.length);
		break;

	default:
		return_ACPI_STATUS(AE_TYPE);
	}

	/* Mark buffer initialized */

	return_desc->common.flags |= AOPOBJ_DATA_VALID;
	*result_desc = return_desc;
	return_ACPI_STATUS(AE_OK);
}
static ACPI_STATUS
OslGetTableViaRoot (
    char                    *Signature,
    UINT32                  Instance,
    ACPI_TABLE_HEADER       **Table,
    ACPI_PHYSICAL_ADDRESS   *Address)
{
    ACPI_TABLE_HEADER       *LocalTable = NULL;
    ACPI_TABLE_HEADER       *MappedTable = NULL;
    UINT8                   NumberOfTables;
    UINT32                  CurrentInstance = 0;
    ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
    ACPI_STATUS             Status;
    UINT32                  i;


    /* DSDT and FACS address must be extracted from the FADT */

    if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
        ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
    {
        /*
         * Get the appropriate address, either 32-bit or 64-bit. Be very
         * careful about the FADT length and validate table addresses.
         * Note: The 64-bit addresses have priority.
         */
        if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
        {
            if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
                Gbl_Fadt->XDsdt)
            {
                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
            }
            else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
                Gbl_Fadt->Dsdt)
            {
                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
            }
        }
        else /* FACS */
        {
            if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
                Gbl_Fadt->XFacs)
            {
                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
            }
            else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
                Gbl_Fadt->Facs)
            {
                TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
            }
        }
    }
    else /* Case for a normal ACPI table */
    {
        if (Gbl_Revision)
        {
            NumberOfTables =
                (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
                / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
        }
        else /* Use RSDT if XSDT is not available */
        {
            NumberOfTables =
                (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
                / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
        }

        /* Search RSDT/XSDT for the requested table */

        for (i = 0; i < NumberOfTables; i++)
        {
            if (Gbl_Revision)
            {
                TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
            }
            else
            {
                TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
            }

            MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
            if (!MappedTable)
            {
                return (AE_BAD_ADDRESS);
            }

            /* Does this table match the requested signature? */

            if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
            {

                /* Match table instance (for SSDT/UEFI tables) */

                if (CurrentInstance == Instance)
                {
                    AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
                    break;
                }

                CurrentInstance++;
            }

            AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
            TableAddress = 0;
        }
    }

    if (!TableAddress)
    {
        if (CurrentInstance)
        {
            return (AE_LIMIT);
        }
        return (AE_NOT_FOUND);
    }

    /* Now we can get the requested table */

    Status = OslMapTable (TableAddress, Signature, &MappedTable);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    /* Copy table to local buffer and return it */

    LocalTable = calloc (1, MappedTable->Length);
    if (!LocalTable)
    {
        AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
        return (AE_NO_MEMORY);
    }

    ACPI_MEMCPY (LocalTable, MappedTable, MappedTable->Length);
    AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
    *Table = LocalTable;
    *Address = TableAddress;
    return (AE_OK);
}
Example #24
0
acpi_status acpi_ex_opcode_3A_1T_1R(struct acpi_walk_state *walk_state)
{
	union acpi_operand_object **operand = &walk_state->operands[0];
	union acpi_operand_object *return_desc = NULL;
	char *buffer = NULL;
	acpi_status status = AE_OK;
	u64 index;
	acpi_size length;

	ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_1T_1R,
				acpi_ps_get_opcode_name(walk_state->opcode));

	switch (walk_state->opcode) {
	case AML_MID_OP:	/* Mid (Source[0], Index[1], Length[2], Result[3]) */

		/*
		 * Create the return object. The Source operand is guaranteed to be
		 * either a String or a Buffer, so just use its type.
		 */
		return_desc = acpi_ut_create_internal_object((operand[0])->
							     common.type);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Get the Integer values from the objects */

		index = operand[1]->integer.value;
		length = (acpi_size) operand[2]->integer.value;

		/*
		 * If the index is beyond the length of the String/Buffer, or if the
		 * requested length is zero, return a zero-length String/Buffer
		 */
		if (index >= operand[0]->string.length) {
			length = 0;
		}

		/* Truncate request if larger than the actual String/Buffer */

		else if ((index + length) > operand[0]->string.length) {
			length = (acpi_size) operand[0]->string.length -
			    (acpi_size) index;
		}

		/* Strings always have a sub-pointer, not so for buffers */

		switch ((operand[0])->common.type) {
		case ACPI_TYPE_STRING:

			/* Always allocate a new buffer for the String */

			buffer = ACPI_ALLOCATE_ZEROED((acpi_size) length + 1);
			if (!buffer) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}
			break;

		case ACPI_TYPE_BUFFER:

			/* If the requested length is zero, don't allocate a buffer */

			if (length > 0) {

				/* Allocate a new buffer for the Buffer */

				buffer = ACPI_ALLOCATE_ZEROED(length);
				if (!buffer) {
					status = AE_NO_MEMORY;
					goto cleanup;
				}
			}
			break;

		default:	/* Should not happen */

			status = AE_AML_OPERAND_TYPE;
			goto cleanup;
		}

		if (buffer) {

			/* We have a buffer, copy the portion requested */

			ACPI_MEMCPY(buffer, operand[0]->string.pointer + index,
				    length);
		}

		/* Set the length of the new String/Buffer */

		return_desc->string.pointer = buffer;
		return_desc->string.length = (u32) length;

		/* Mark buffer initialized */

		return_desc->buffer.flags |= AOPOBJ_DATA_VALID;
		break;

	default:

		ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
			    walk_state->opcode));
		status = AE_AML_BAD_OPCODE;
		goto cleanup;
	}

	/* Store the result in the target */

	status = acpi_ex_store(return_desc, operand[3], walk_state);

      cleanup:

	/* Delete return object on error */

	if (ACPI_FAILURE(status) || walk_state->result_obj) {
		acpi_ut_remove_reference(return_desc);
		walk_state->result_obj = NULL;
	}

	/* Set the return object and exit */

	else {
		walk_state->result_obj = return_desc;
	}
	return_ACPI_STATUS(status);
}
Example #25
0
acpi_status
acpi_ex_do_concatenate (
	union acpi_operand_object       *operand0,
	union acpi_operand_object       *operand1,
	union acpi_operand_object       **actual_return_desc,
	struct acpi_walk_state          *walk_state)
{
	union acpi_operand_object       *local_operand1 = operand1;
	union acpi_operand_object       *return_desc;
	char                            *new_buf;
	acpi_status                     status;
	acpi_size                       new_length;


	ACPI_FUNCTION_TRACE ("ex_do_concatenate");


	/*
	 * Convert the second operand if necessary.  The first operand
	 * determines the type of the second operand, (See the Data Types
	 * section of the ACPI specification.)  Both object types are
	 * guaranteed to be either Integer/String/Buffer by the operand
	 * resolution mechanism.
	 */
	switch (ACPI_GET_OBJECT_TYPE (operand0)) {
	case ACPI_TYPE_INTEGER:
		status = acpi_ex_convert_to_integer (operand1, &local_operand1, 16);
		break;

	case ACPI_TYPE_STRING:
		status = acpi_ex_convert_to_string (operand1, &local_operand1,
				 ACPI_IMPLICIT_CONVERT_HEX);
		break;

	case ACPI_TYPE_BUFFER:
		status = acpi_ex_convert_to_buffer (operand1, &local_operand1);
		break;

	default:
		ACPI_REPORT_ERROR (("Concat - invalid obj type: %X\n",
				ACPI_GET_OBJECT_TYPE (operand0)));
		status = AE_AML_INTERNAL;
	}

	if (ACPI_FAILURE (status)) {
		goto cleanup;
	}

	/*
	 * Both operands are now known to be the same object type
	 * (Both are Integer, String, or Buffer), and we can now perform the
	 * concatenation.
	 */

	/*
	 * There are three cases to handle:
	 *
	 * 1) Two Integers concatenated to produce a new Buffer
	 * 2) Two Strings concatenated to produce a new String
	 * 3) Two Buffers concatenated to produce a new Buffer
	 */
	switch (ACPI_GET_OBJECT_TYPE (operand0)) {
	case ACPI_TYPE_INTEGER:

		/* Result of two Integers is a Buffer */
		/* Need enough buffer space for two integers */

		return_desc = acpi_ut_create_buffer_object (
				   ACPI_MUL_2 (acpi_gbl_integer_byte_width));
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		new_buf = (char *) return_desc->buffer.pointer;

		/* Copy the first integer, LSB first */

		ACPI_MEMCPY (new_buf,
				  &operand0->integer.value,
				  acpi_gbl_integer_byte_width);

		/* Copy the second integer (LSB first) after the first */

		ACPI_MEMCPY (new_buf + acpi_gbl_integer_byte_width,
				  &local_operand1->integer.value,
				  acpi_gbl_integer_byte_width);
		break;

	case ACPI_TYPE_STRING:

		/* Result of two Strings is a String */

		new_length = (acpi_size) operand0->string.length +
				 (acpi_size) local_operand1->string.length;
		if (new_length > ACPI_MAX_STRING_CONVERSION) {
			status = AE_AML_STRING_LIMIT;
			goto cleanup;
		}

		return_desc = acpi_ut_create_string_object (new_length);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		new_buf = return_desc->string.pointer;

		/* Concatenate the strings */

		ACPI_STRCPY (new_buf,
				  operand0->string.pointer);
		ACPI_STRCPY (new_buf + operand0->string.length,
				  local_operand1->string.pointer);
		break;

	case ACPI_TYPE_BUFFER:

		/* Result of two Buffers is a Buffer */

		return_desc = acpi_ut_create_buffer_object (
				   (acpi_size) operand0->buffer.length +
				   (acpi_size) local_operand1->buffer.length);
		if (!return_desc) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		new_buf = (char *) return_desc->buffer.pointer;

		/* Concatenate the buffers */

		ACPI_MEMCPY (new_buf,
				  operand0->buffer.pointer,
				  operand0->buffer.length);
		ACPI_MEMCPY (new_buf + operand0->buffer.length,
				  local_operand1->buffer.pointer,
				  local_operand1->buffer.length);
		break;

	default:

		/* Invalid object type, should not happen here */

		ACPI_REPORT_ERROR (("Concatenate - Invalid object type: %X\n",
				ACPI_GET_OBJECT_TYPE (operand0)));
		status =AE_AML_INTERNAL;
		goto cleanup;
	}

	*actual_return_desc = return_desc;

cleanup:
	if (local_operand1 != operand1) {
		acpi_ut_remove_reference (local_operand1);
	}
	return_ACPI_STATUS (AE_OK);
}
Example #26
0
static acpi_status
acpi_tb_get_this_table (
	struct acpi_pointer             *address,
	struct acpi_table_header        *header,
	struct acpi_table_desc          *table_info)
{
	struct acpi_table_header        *full_table = NULL;
	u8                              allocation;
	acpi_status                     status = AE_OK;


	ACPI_FUNCTION_TRACE ("tb_get_this_table");


	/*
	 * Flags contains the current processor mode (Virtual or Physical
	 * addressing) The pointer_type is either Logical or Physical
	 */
	switch (address->pointer_type) {
	case ACPI_PHYSMODE_PHYSPTR:
	case ACPI_LOGMODE_LOGPTR:

		/* Pointer matches processor mode, copy the table to a new buffer */

		full_table = ACPI_MEM_ALLOCATE (header->length);
		if (!full_table) {
			ACPI_REPORT_ERROR ((
				"Could not allocate table memory for [%4.4s] length %X\n",
				header->signature, header->length));
			return_ACPI_STATUS (AE_NO_MEMORY);
		}

		/* Copy the entire table (including header) to the local buffer */

		ACPI_MEMCPY (full_table, address->pointer.logical, header->length);

		/* Save allocation type */

		allocation = ACPI_MEM_ALLOCATED;
		break;


	case ACPI_LOGMODE_PHYSPTR:

		/*
		 * Just map the table's physical memory
		 * into our address space.
		 */
		status = acpi_os_map_memory (address->pointer.physical,
				 (acpi_size) header->length, (void *) &full_table);
		if (ACPI_FAILURE (status)) {
			ACPI_REPORT_ERROR ((
				"Could not map memory for table [%4.4s] at %8.8X%8.8X for length %X\n",
				header->signature,
				ACPI_FORMAT_UINT64 (address->pointer.physical),
				header->length));
			return (status);
		}

		/* Save allocation type */

		allocation = ACPI_MEM_MAPPED;
		break;


	default:

		ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid address flags %X\n",
			address->pointer_type));
		return_ACPI_STATUS (AE_BAD_PARAMETER);
	}

	/*
	 * Validate checksum for _most_ tables,
	 * even the ones whose signature we don't recognize
	 */
	if (table_info->type != ACPI_TABLE_FACS) {
		status = acpi_tb_verify_table_checksum (full_table);

#if (!ACPI_CHECKSUM_ABORT)
		if (ACPI_FAILURE (status)) {
			/* Ignore the error if configuration says so */

			status = AE_OK;
		}
#endif
	}

	/* Return values */

	table_info->pointer     = full_table;
	table_info->length      = (acpi_size) header->length;
	table_info->allocation  = allocation;

	ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
		"Found table [%4.4s] at %8.8X%8.8X, mapped/copied to %p\n",
		full_table->signature,
		ACPI_FORMAT_UINT64 (address->pointer.physical), full_table));

	return_ACPI_STATUS (status);
}
Example #27
0
ACPI_STATUS
AcpiExStoreBufferToBuffer (
    ACPI_OPERAND_OBJECT     *SourceDesc,
    ACPI_OPERAND_OBJECT     *TargetDesc)
{
    UINT32                  Length;
    UINT8                   *Buffer;


    ACPI_FUNCTION_TRACE_PTR (ExStoreBufferToBuffer, SourceDesc);


    /* If Source and Target are the same, just return */

    if (SourceDesc == TargetDesc)
    {
        return_ACPI_STATUS (AE_OK);
    }

    /* We know that SourceDesc is a buffer by now */

    Buffer = ACPI_CAST_PTR (UINT8, SourceDesc->Buffer.Pointer);
    Length = SourceDesc->Buffer.Length;

    /*
     * If target is a buffer of length zero or is a static buffer,
     * allocate a new buffer of the proper length
     */
    if ((TargetDesc->Buffer.Length == 0) ||
        (TargetDesc->Common.Flags & AOPOBJ_STATIC_POINTER))
    {
        TargetDesc->Buffer.Pointer = ACPI_ALLOCATE (Length);
        if (!TargetDesc->Buffer.Pointer)
        {
            return_ACPI_STATUS (AE_NO_MEMORY);
        }

        TargetDesc->Buffer.Length = Length;
    }

    /* Copy source buffer to target buffer */

    if (Length <= TargetDesc->Buffer.Length)
    {
        /* Clear existing buffer and copy in the new one */

        ACPI_MEMSET (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length);
        ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer, Length);

#ifdef ACPI_OBSOLETE_BEHAVIOR
        /*
         * NOTE: ACPI versions up to 3.0 specified that the buffer must be
         * truncated if the string is smaller than the buffer. However, "other"
         * implementations of ACPI never did this and thus became the defacto
         * standard. ACPI 3.0A changes this behavior such that the buffer
         * is no longer truncated.
         */

        /*
         * OBSOLETE BEHAVIOR:
         * If the original source was a string, we must truncate the buffer,
         * according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
         * copy must not truncate the original buffer.
         */
        if (OriginalSrcType == ACPI_TYPE_STRING)
        {
            /* Set the new length of the target */

            TargetDesc->Buffer.Length = Length;
        }
#endif
    }
    else
    {
        /* Truncate the source, copy only what will fit */

        ACPI_MEMCPY (TargetDesc->Buffer.Pointer, Buffer,
            TargetDesc->Buffer.Length);

        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "Truncating source buffer from %X to %X\n",
            Length, TargetDesc->Buffer.Length));
    }

    /* Copy flags */

    TargetDesc->Buffer.Flags = SourceDesc->Buffer.Flags;
    TargetDesc->Common.Flags &= ~AOPOBJ_STATIC_POINTER;
    return_ACPI_STATUS (AE_OK);
}
Example #28
0
void
DtCompileInteger (
    UINT8                   *Buffer,
    DT_FIELD                *Field,
    UINT32                  ByteLength,
    UINT8                   Flags)
{
    UINT64                  Value;
    UINT64                  MaxValue;
    ACPI_STATUS             Status;


    /* Output buffer byte length must be in range 1-8 */

    if ((ByteLength > 8) || (ByteLength == 0))
    {
        DtFatal (ASL_MSG_COMPILER_INTERNAL, Field,
            "Invalid internal Byte length");
        return;
    }

    /* Resolve integer expression to a single integer value */

    Status = DtResolveIntegerExpression (Field, &Value);
    if (ACPI_FAILURE (Status))
    {
        return;
    }

    /*
     * Ensure that reserved fields are set properly. Note: uses
     * the DT_NON_ZERO flag to indicate that the reserved value
     * must be exactly one. Otherwise, the value must be zero.
     * This is sufficient for now.
     */

    /* TBD: Should use a flag rather than compare "Reserved" */

    if (!ACPI_STRCMP (Field->Name, "Reserved"))
    {
        if (Flags & DT_NON_ZERO)
        {
            if (Value != 1)
            {
                DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
                    "Must be one, setting to one");
                Value = 1;
            }
        }
        else if (Value != 0)
        {
            DtError (ASL_WARNING, ASL_MSG_RESERVED_VALUE, Field,
                "Must be zero, setting to zero");
            Value = 0;
        }
    }

    /* Check if the value must be non-zero */

    else if ((Flags & DT_NON_ZERO) && (Value == 0))
    {
        DtError (ASL_ERROR, ASL_MSG_ZERO_VALUE, Field, NULL);
    }

    /*
     * Generate the maximum value for the data type (ByteLength)
     * Note: construct chosen for maximum portability
     */
    MaxValue = ((UINT64) (-1)) >> (64 - (ByteLength * 8));

    /* Validate that the input value is within range of the target */

    if (Value > MaxValue)
    {
        sprintf (MsgBuffer, "%8.8X%8.8X - max %u bytes",
            ACPI_FORMAT_UINT64 (Value), ByteLength);
        DtError (ASL_ERROR, ASL_MSG_INTEGER_SIZE, Field, MsgBuffer);
    }

    ACPI_MEMCPY (Buffer, &Value, ByteLength);
    return;
}
Example #29
0
acpi_status
acpi_ut_copy_simple_object (
	union acpi_operand_object       *source_desc,
	union acpi_operand_object       *dest_desc)
{
	u16                             reference_count;
	union acpi_operand_object       *next_object;


	/* Save fields from destination that we don't want to overwrite */

	reference_count = dest_desc->common.reference_count;
	next_object = dest_desc->common.next_object;

	/* Copy the entire source object over the destination object*/

	ACPI_MEMCPY ((char *) dest_desc, (char *) source_desc,
			  sizeof (union acpi_operand_object));

	/* Restore the saved fields */

	dest_desc->common.reference_count = reference_count;
	dest_desc->common.next_object = next_object;

	/* Handle the objects with extra data */

	switch (ACPI_GET_OBJECT_TYPE (dest_desc)) {
	case ACPI_TYPE_BUFFER:

		dest_desc->buffer.node = NULL;
		dest_desc->common.flags = source_desc->common.flags;

		/*
		 * Allocate and copy the actual buffer if and only if:
		 * 1) There is a valid buffer pointer
		 * 2) The buffer is not static (not in an ACPI table) (in this case,
		 *    the actual pointer was already copied above)
		 */
		if ((source_desc->buffer.pointer) &&
			(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
			dest_desc->buffer.pointer = NULL;

			/* Create an actual buffer only if length > 0 */

			if (source_desc->buffer.length) {
				dest_desc->buffer.pointer =
					ACPI_MEM_ALLOCATE (source_desc->buffer.length);
				if (!dest_desc->buffer.pointer) {
					return (AE_NO_MEMORY);
				}

				/* Copy the actual buffer data */

				ACPI_MEMCPY (dest_desc->buffer.pointer,
						source_desc->buffer.pointer,
						source_desc->buffer.length);
			}
		}
		break;

	case ACPI_TYPE_STRING:

		/*
		 * Allocate and copy the actual string if and only if:
		 * 1) There is a valid string pointer
		 * 2) The string is not static (not in an ACPI table) (in this case,
		 *    the actual pointer was already copied above)
		 */
		if ((source_desc->string.pointer) &&
			(!(source_desc->common.flags & AOPOBJ_STATIC_POINTER))) {
			dest_desc->string.pointer =
				ACPI_MEM_ALLOCATE ((acpi_size) source_desc->string.length + 1);
			if (!dest_desc->string.pointer) {
				return (AE_NO_MEMORY);
			}

			ACPI_MEMCPY (dest_desc->string.pointer, source_desc->string.pointer,
					  (acpi_size) source_desc->string.length + 1);
		}
		break;

	case ACPI_TYPE_LOCAL_REFERENCE:
		/*
		 * We copied the reference object, so we now must add a reference
		 * to the object pointed to by the reference
		 */
		acpi_ut_add_reference (source_desc->reference.object);
		break;

	default:
		/* Nothing to do for other simple objects */
		break;
	}

	return (AE_OK);
}
Example #30
0
acpi_status
acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device,
			 struct acpi_generic_address *gpe_block_address,
			 u32 register_count,
			 u8 gpe_block_base_number,
			 u32 interrupt_number,
			 struct acpi_gpe_block_info **return_gpe_block)
{
	acpi_status status;
	struct acpi_gpe_block_info *gpe_block;

	ACPI_FUNCTION_TRACE(ev_create_gpe_block);

	if (!register_count) {
		return_ACPI_STATUS(AE_OK);
	}

	/* Allocate a new GPE block */

	gpe_block = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_block_info));
	if (!gpe_block) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Initialize the new GPE block */

	gpe_block->node = gpe_device;
	gpe_block->register_count = register_count;
	gpe_block->block_base_number = gpe_block_base_number;

	ACPI_MEMCPY(&gpe_block->block_address, gpe_block_address,
		    sizeof(struct acpi_generic_address));

	/*
	 * Create the register_info and event_info sub-structures
	 * Note: disables and clears all GPEs in the block
	 */
	status = acpi_ev_create_gpe_info_blocks(gpe_block);
	if (ACPI_FAILURE(status)) {
		ACPI_FREE(gpe_block);
		return_ACPI_STATUS(status);
	}

	/* Install the new block in the global lists */

	status = acpi_ev_install_gpe_block(gpe_block, interrupt_number);
	if (ACPI_FAILURE(status)) {
		ACPI_FREE(gpe_block);
		return_ACPI_STATUS(status);
	}

	/* Find all GPE methods (_Lxx, _Exx) for this block */

	status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device,
					ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
					acpi_ev_save_method_info, gpe_block,
					NULL);

	/* Return the new block */

	if (return_gpe_block) {
		(*return_gpe_block) = gpe_block;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_INIT,
			  "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n",
			  (u32) gpe_block->block_base_number,
			  (u32) (gpe_block->block_base_number +
				 ((gpe_block->register_count *
				   ACPI_GPE_REGISTER_WIDTH) - 1)),
			  gpe_device->name.ascii, gpe_block->register_count,
			  interrupt_number));

	/* Update global count of currently available GPEs */

	acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH;
	return_ACPI_STATUS(AE_OK);
}