Пример #1
0
ACPI_STATUS
AdAmlDisassemble (
    BOOLEAN                 OutToFile,
    char                    *Filename,
    char                    *Prefix,
    char                    **OutFilename,
    BOOLEAN                 GetAllTables)
{
    ACPI_STATUS             Status;
    char                    *DisasmFilename = NULL;
    char                    *ExternalFilename;
    FILE                    *File = NULL;
    ACPI_TABLE_HEADER       *Table = NULL;
    ACPI_TABLE_HEADER       *ExternalTable;
    ACPI_OWNER_ID           OwnerId;


    /*
     * Input: AML code from either a file or via GetTables (memory or
     * registry)
     */
    if (Filename)
    {
        Status = AcpiDbGetTableFromFile (Filename, &Table);
        if (ACPI_FAILURE (Status))
        {
            return Status;
        }

        /*
         * External filenames separated by commas
         * Example: iasl -e file1,file2,file3 -d xxx.aml
         */
        if (Gbl_ExternalFilename)
        {
            ExternalFilename = strtok (Gbl_ExternalFilename, ",");

            while (ExternalFilename)
            {
                Status = AcpiDbGetTableFromFile (ExternalFilename, &ExternalTable);
                if (ACPI_FAILURE (Status))
                {
                    return Status;
                }

                /* Load external table for symbol resolution */

                if (ExternalTable)
                {
                    Status = AdParseTable (ExternalTable, &OwnerId, TRUE, TRUE);
                    if (ACPI_FAILURE (Status))
                    {
                        AcpiOsPrintf ("Could not parse external ACPI tables, %s\n",
                            AcpiFormatException (Status));
                        return Status;
                    }

                    /*
                     * Load namespace from names created within control methods
                     * Set owner id of nodes in external table
                     */
                    AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot,
                        AcpiGbl_RootNode, OwnerId);
                    AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
                }

                /* Next external file name */

                ExternalFilename = strtok (NULL, ",");
            }

            /* Clear external list generated by Scope in external tables */

            AcpiDmClearExternalList ();
        }
    }
    else
    {
        Status = AdGetLocalTables (Filename, GetAllTables);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not get ACPI tables, %s\n",
                AcpiFormatException (Status));
            return Status;
        }

        if (!AcpiGbl_DbOpt_disasm)
        {
            return AE_OK;
        }

        /* Obtained the local tables, just disassemble the DSDT */

        Status = AcpiGetTable (ACPI_SIG_DSDT, 0, &Table);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not get DSDT, %s\n",
                AcpiFormatException (Status));
            return Status;
        }

        AcpiOsPrintf ("\nDisassembly of DSDT\n");
        Prefix = AdGenerateFilename ("dsdt", Table->OemTableId);
    }

    /*
     * Output:  ASL code. Redirect to a file if requested
     */
    if (OutToFile)
    {
        /* Create/Open a disassembly output file */

        DisasmFilename = FlGenerateFilename (Prefix, FILE_SUFFIX_DISASSEMBLY);
        if (!OutFilename)
        {
            fprintf (stderr, "Could not generate output filename\n");
            Status = AE_ERROR;
            goto Cleanup;
        }

        File = fopen (DisasmFilename, "w+");
        if (!File)
        {
            fprintf (stderr, "Could not open output file %s\n", DisasmFilename);
            Status = AE_ERROR;
            goto Cleanup;
        }

        AcpiOsRedirectOutput (File);
    }

    *OutFilename = DisasmFilename;

    if (!AcpiUtIsAmlTable (Table))
    {
        AdDisassemblerHeader (Filename);
        AcpiOsPrintf (" * ACPI Data Table [%4.4s]\n *\n",
            Table->Signature);
        AcpiOsPrintf (" * Format: [HexOffset DecimalOffset ByteLength]  FieldName : FieldValue\n */\n\n");

        AcpiDmDumpDataTable (Table);
        fprintf (stderr, "Acpi Data Table [%4.4s] decoded, written to \"%s\"\n",
            Table->Signature, DisasmFilename);
    }
    else
    {
        /* Always parse the tables, only option is what to display */

        Status = AdParseTable (Table, &OwnerId, TRUE, FALSE);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
                AcpiFormatException (Status));
            goto Cleanup;
        }

        if (AslCompilerdebug)
        {
            AcpiOsPrintf ("/**** Before second load\n");

            LsSetupNsList (File);
            LsDisplayNamespace ();
            AcpiOsPrintf ("*****/\n");
        }

        /*
         * Load namespace from names created within control methods
         */
        AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId);

        /*
         * Cross reference the namespace here, in order to generate External() statements
         */
        AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId);

        if (AslCompilerdebug)
        {
            AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
        }

        /* Find possible calls to external control methods */

        AcpiDmFindOrphanMethods (AcpiGbl_ParseOpRoot);

        /* Convert fixed-offset references to resource descriptors to symbolic references */

        AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode);

        /*
         * If we found any external control methods, we must reparse the entire
         * tree with the new information (namely, the number of arguments per
         * method)
         */
        if (AcpiDmGetExternalMethodCount ())
        {
            fprintf (stderr,
                "\nFound %d external control methods, reparsing with new information\n",
                AcpiDmGetExternalMethodCount ());

            /*
             * Reparse, rebuild namespace. no need to xref namespace
             */
            AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
            AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode);

            AcpiGbl_RootNode                    = NULL;
            AcpiGbl_RootNodeStruct.Name.Integer = ACPI_ROOT_NAME;
            AcpiGbl_RootNodeStruct.DescriptorType = ACPI_DESC_TYPE_NAMED;
            AcpiGbl_RootNodeStruct.Type         = ACPI_TYPE_DEVICE;
            AcpiGbl_RootNodeStruct.Child        = NULL;
            AcpiGbl_RootNodeStruct.Peer         = NULL;
            AcpiGbl_RootNodeStruct.Object       = NULL;
            AcpiGbl_RootNodeStruct.Flags        = ANOBJ_END_OF_PEER_LIST;

            Status = AcpiNsRootInitialize ();
            AcpiDmAddExternalsToNamespace ();

            /* Parse table. No need to reload it, however (FALSE) */

            Status = AdParseTable (Table, NULL, FALSE, FALSE);
            if (ACPI_FAILURE (Status))
            {
                AcpiOsPrintf ("Could not parse ACPI tables, %s\n",
                    AcpiFormatException (Status));
                goto Cleanup;
            }

            if (AslCompilerdebug)
            {
                AcpiOsPrintf ("/**** After second load and resource conversion\n");
                LsSetupNsList (File);
                LsDisplayNamespace ();
                AcpiOsPrintf ("*****/\n");

                AcpiDmDumpTree (AcpiGbl_ParseOpRoot);
            }
        }

        /* Optional displays */

        if (AcpiGbl_DbOpt_disasm)
        {
            AdDisplayTables (Filename, Table);
            fprintf (stderr,
                "Disassembly completed, written to \"%s\"\n",
                DisasmFilename);
        }
    }

Cleanup:

    if (Table && !AcpiUtIsAmlTable (Table))
    {
        ACPI_FREE (Table);
    }

    if (DisasmFilename)
    {
        ACPI_FREE (DisasmFilename);
    }

    if (OutToFile && File)
    {

#ifdef ASL_DISASM_DEBUG
        LsSetupNsList (File);
        LsDisplayNamespace ();
#endif
        fclose (File);
        AcpiOsRedirectOutput (stdout);
    }

    AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot);
    AcpiGbl_ParseOpRoot = NULL;
    return (Status);
}
Пример #2
0
static ACPI_STATUS
AcpiNsInitOneDevice (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
    UINT32                  Flags;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *DeviceNode;


    ACPI_FUNCTION_TRACE (NsInitOneDevice);


    /* We are interested in Devices, Processors and ThermalZones only */

    DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
        (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
        (DeviceNode->Type != ACPI_TYPE_THERMAL))
    {
        return_ACPI_STATUS (AE_OK);
    }

    /*
     * Because of an earlier namespace analysis, all subtrees that contain an
     * _INI method are tagged.
     *
     * If this device subtree does not contain any _INI methods, we
     * can exit now and stop traversing this entire subtree.
     */
    if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
    {
        return_ACPI_STATUS (AE_CTRL_DEPTH);
    }

    /*
     * Run _STA to determine if this device is present and functioning. We
     * must know this information for two important reasons (from ACPI spec):
     *
     * 1) We can only run _INI if the device is present.
     * 2) We must abort the device tree walk on this subtree if the device is
     *    not present and is not functional (we will not examine the children)
     *
     * The _STA method is not required to be present under the device, we
     * assume the device is present if _STA does not exist.
     */
    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));

    Status = AcpiUtExecute_STA (DeviceNode, &Flags);
    if (ACPI_FAILURE (Status))
    {
        /* Ignore error and move on to next device */

        return_ACPI_STATUS (AE_OK);
    }

    /*
     * Flags == -1 means that _STA was not found. In this case, we assume that
     * the device is both present and functional.
     *
     * From the ACPI spec, description of _STA:
     *
     * "If a device object (including the processor object) does not have an
     * _STA object, then OSPM assumes that all of the above bits are set (in
     * other words, the device is present, ..., and functioning)"
     */
    if (Flags != ACPI_UINT32_MAX)
    {
        WalkInfo->Num_STA++;
    }

    /*
     * Examine the PRESENT and FUNCTIONING status bits
     *
     * Note: ACPI spec does not seem to specify behavior for the present but
     * not functioning case, so we assume functioning if present.
     */
    if (!(Flags & ACPI_STA_DEVICE_PRESENT))
    {
        /* Device is not present, we must examine the Functioning bit */

        if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
        {
            /*
             * Device is not present but is "functioning". In this case,
             * we will not run _INI, but we continue to examine the children
             * of this device.
             *
             * From the ACPI spec, description of _STA: (Note - no mention
             * of whether to run _INI or not on the device in question)
             *
             * "_STA may return bit 0 clear (not present) with bit 3 set
             * (device is functional). This case is used to indicate a valid
             * device for which no device driver should be loaded (for example,
             * a bridge device.) Children of this device may be present and
             * valid. OSPM should continue enumeration below a device whose
             * _STA returns this bit combination"
             */
            return_ACPI_STATUS (AE_OK);
        }
        else
        {
            /*
             * Device is not present and is not functioning. We must abort the
             * walk of this subtree immediately -- don't look at the children
             * of such a device.
             *
             * From the ACPI spec, description of _INI:
             *
             * "If the _STA method indicates that the device is not present,
             * OSPM will not run the _INI and will not examine the children
             * of the device for _INI methods"
             */
            return_ACPI_STATUS (AE_CTRL_DEPTH);
        }
    }

    /*
     * The device is present or is assumed present if no _STA exists.
     * Run the _INI if it exists (not required to exist)
     *
     * Note: We know there is an _INI within this subtree, but it may not be
     * under this particular device, it may be lower in the branch.
     */
    ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
        ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));

    memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
    Info->PrefixNode = DeviceNode;
    Info->RelativePathname = __UNCONST(METHOD_NAME__INI);
    Info->Parameters = NULL;
    Info->Flags = ACPI_IGNORE_RETURN_VALUE;

    Status = AcpiNsEvaluate (Info);
    if (ACPI_SUCCESS (Status))
    {
        WalkInfo->Num_INI++;
    }

#ifdef ACPI_DEBUG_OUTPUT
    else if (Status != AE_NOT_FOUND)
    {
        /* Ignore error and move on to next device */

        char *ScopeName = AcpiNsGetExternalPathname (Info->Node);

        ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
            ScopeName));
        ACPI_FREE (ScopeName);
    }
#endif

    /* Ignore errors from above */

    Status = AE_OK;

    /*
     * The _INI method has been run if present; call the Global Initialization
     * Handler for this device.
     */
    if (AcpiGbl_InitHandler)
    {
        Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
    }

    return_ACPI_STATUS (Status);
}
Пример #3
0
static ACPI_STATUS
AcpiDmTestResourceConversion (
    ACPI_NAMESPACE_NODE     *Node,
    char                    *Name)
{
    ACPI_STATUS             Status;
    ACPI_BUFFER             ReturnBuffer;
    ACPI_BUFFER             ResourceBuffer;
    ACPI_BUFFER             NewAml;
    ACPI_OBJECT             *OriginalAml;


    AcpiOsPrintf ("Resource Conversion Comparison:\n");

    NewAml.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    ReturnBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    ResourceBuffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;

    /* Get the original _CRS AML resource template */

    Status = AcpiEvaluateObject (Node, Name, NULL, &ReturnBuffer);
    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("Could not obtain %s: %s\n",
            Name, AcpiFormatException (Status));
        return (Status);
    }

    /* Get the AML resource template, converted to internal resource structs */

    Status = AcpiGetCurrentResources (Node, &ResourceBuffer);
    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
            AcpiFormatException (Status));
        goto Exit1;
    }

    /* Convert internal resource list to external AML resource template */

    Status = AcpiRsCreateAmlResources (ResourceBuffer.Pointer, &NewAml);
    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("AcpiRsCreateAmlResources failed: %s\n",
            AcpiFormatException (Status));
        goto Exit2;
    }

    /* Compare original AML to the newly created AML resource list */

    OriginalAml = ReturnBuffer.Pointer;

    AcpiDmCompareAmlResources (
        OriginalAml->Buffer.Pointer, (ACPI_RSDESC_SIZE) OriginalAml->Buffer.Length,
        NewAml.Pointer, (ACPI_RSDESC_SIZE) NewAml.Length);

    /* Cleanup and exit */

    ACPI_FREE (NewAml.Pointer);
Exit2:
    ACPI_FREE (ResourceBuffer.Pointer);
Exit1:
    ACPI_FREE (ReturnBuffer.Pointer);
    return (Status);
}
Пример #4
0
ACPI_STATUS
AcpiExOpcode_3A_0T_0R (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_OPERAND_OBJECT     **Operand = &WalkState->Operands[0];
    ACPI_SIGNAL_FATAL_INFO  *Fatal;
    ACPI_STATUS             Status = AE_OK;


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


    switch (WalkState->Opcode)
    {
    case AML_FATAL_OP:          /* Fatal (FatalType  FatalCode  FatalArg) */

        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
            "FatalOp: Type %X Code %X Arg %X "
            "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
            (UINT32) Operand[0]->Integer.Value,
            (UINT32) Operand[1]->Integer.Value,
            (UINT32) Operand[2]->Integer.Value));

        Fatal = ACPI_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO));
        if (Fatal)
        {
            Fatal->Type = (UINT32) Operand[0]->Integer.Value;
            Fatal->Code = (UINT32) Operand[1]->Integer.Value;
            Fatal->Argument = (UINT32) Operand[2]->Integer.Value;
        }

        /* Always signal the OS! */

        Status = AcpiOsSignal (ACPI_SIGNAL_FATAL, Fatal);

        /* Might return while OS is shutting down, just continue */

        ACPI_FREE (Fatal);
        goto Cleanup;

    case AML_EXTERNAL_OP:
        /*
         * If the interpreter sees this opcode, just ignore it. The External
         * op is intended for use by disassemblers in order to properly
         * disassemble control method invocations. The opcode or group of
         * opcodes should be surrounded by an "if (0)" clause to ensure that
         * AML interpreters never see the opcode. Thus, something is
         * wrong if an external opcode ever gets here.
         */
        ACPI_ERROR ((AE_INFO, "Executed External Op"));
        Status = AE_OK;
        goto Cleanup;

    default:

        ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X",
            WalkState->Opcode));

        Status = AE_AML_BAD_OPCODE;
        goto Cleanup;
    }


Cleanup:

    return_ACPI_STATUS (Status);
}
Пример #5
0
static ACPI_STATUS
AcpiDbTestBufferType (
    ACPI_NAMESPACE_NODE     *Node,
    UINT32                  BitLength)
{
    ACPI_OBJECT             *Temp1 = NULL;
    ACPI_OBJECT             *Temp2 = NULL;
    ACPI_OBJECT             *Temp3 = NULL;
    UINT8                   *Buffer;
    ACPI_OBJECT             WriteValue;
    ACPI_STATUS             Status;
    UINT32                  ByteLength;
    UINT32                  i;
    UINT8                   ExtraBits;


    ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength);
    if (ByteLength == 0)
    {
        AcpiOsPrintf (" Ignoring zero length buffer");
        return (AE_OK);
    }

    /* Allocate a local buffer */

    Buffer = ACPI_ALLOCATE_ZEROED (ByteLength);
    if (!Buffer)
    {
        return (AE_NO_MEMORY);
    }

    /* Read the original value */

    Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp1);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    /* Emit a few bytes of the buffer */

    AcpiOsPrintf (" (%4.4X/%3.3X)", BitLength, Temp1->Buffer.Length);
    for (i = 0; ((i < 4) && (i < ByteLength)); i++)
    {
        AcpiOsPrintf (" %2.2X", Temp1->Buffer.Pointer[i]);
    }
    AcpiOsPrintf ("...  ");

    /*
     * Write a new value.
     *
     * Handle possible extra bits at the end of the buffer. Can
     * happen for FieldUnits larger than an integer, but the bit
     * count is not an integral number of bytes. Zero out the
     * unused bits.
     */
    memset (Buffer, BUFFER_FILL_VALUE, ByteLength);
    ExtraBits = BitLength % 8;
    if (ExtraBits)
    {
        Buffer [ByteLength - 1] = ACPI_MASK_BITS_ABOVE (ExtraBits);
    }

    WriteValue.Type = ACPI_TYPE_BUFFER;
    WriteValue.Buffer.Length = ByteLength;
    WriteValue.Buffer.Pointer = Buffer;

    Status = AcpiDbWriteToObject (Node, &WriteValue);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    /* Ensure that we can read back the new value */

    Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp2);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    if (memcmp (Temp2->Buffer.Pointer, Buffer, ByteLength))
    {
        AcpiOsPrintf (" MISMATCH 2: New buffer value");
    }

    /* Write back the original value */

    WriteValue.Buffer.Length = ByteLength;
    WriteValue.Buffer.Pointer = Temp1->Buffer.Pointer;

    Status = AcpiDbWriteToObject (Node, &WriteValue);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    /* Ensure that we can read back the original value */

    Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp3);
    if (ACPI_FAILURE (Status))
    {
        goto Exit;
    }

    if (memcmp (Temp1->Buffer.Pointer,
            Temp3->Buffer.Pointer, ByteLength))
    {
        AcpiOsPrintf (" MISMATCH 3: While restoring original buffer");
    }

Exit:
    ACPI_FREE (Buffer);
    if (Temp1) {AcpiOsFree (Temp1);}
    if (Temp2) {AcpiOsFree (Temp2);}
    if (Temp3) {AcpiOsFree (Temp3);}
    return (Status);
}
Пример #6
0
static ACPI_STATUS
AcpiNsGetDeviceCallback (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_GET_DEVICES_INFO   *Info = Context;
    ACPI_STATUS             Status;
    ACPI_NAMESPACE_NODE     *Node;
    UINT32                  Flags;
    ACPI_DEVICE_ID          Hid;
    ACPI_COMPATIBLE_ID_LIST *Cid;
    ACPI_NATIVE_UINT        i;
    BOOLEAN                 Found;


    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    Node = AcpiNsMapHandleToNode (ObjHandle);
    Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    if (ACPI_FAILURE (Status))
    {
        return (Status);
    }

    if (!Node)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Run _STA to determine if device is present */

    Status = AcpiUtExecute_STA (Node, &Flags);
    if (ACPI_FAILURE (Status))
    {
        return (AE_CTRL_DEPTH);
    }

    if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
        !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
    {
        /*
         * Don't examine the children of the device only when the
         * device is neither present nor functional. See ACPI spec,
         * description of _STA for more information.
         */
        return (AE_CTRL_DEPTH);
    }

    /* Filter based on device HID & CID */

    if (Info->Hid != NULL)
    {
        Status = AcpiUtExecute_HID (Node, &Hid);
        if (Status == AE_NOT_FOUND)
        {
            return (AE_OK);
        }
        else if (ACPI_FAILURE (Status))
        {
            return (AE_CTRL_DEPTH);
        }

        if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0)
        {
            /*
             * HID does not match, attempt match within the
             * list of Compatible IDs (CIDs)
             */
            Status = AcpiUtExecute_CID (Node, &Cid);
            if (Status == AE_NOT_FOUND)
            {
                return (AE_OK);
            }
            else if (ACPI_FAILURE (Status))
            {
                return (AE_CTRL_DEPTH);
            }

            /* Walk the CID list */

            Found = FALSE;
            for (i = 0; i < Cid->Count; i++)
            {
                if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid,
                        sizeof (ACPI_COMPATIBLE_ID)) == 0)
                {
                    /* Found a matching CID */

                    Found = TRUE;
                    break;
                }
            }

            ACPI_FREE (Cid);
            if (!Found)
            {
                return (AE_OK);
            }
        }
    }

    /* We have a valid device, invoke the user function */

    Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
                ReturnValue);
    return (Status);
}
Пример #7
0
void acpi_db_dump_pld_buffer(union acpi_object *obj_desc)
{
	union acpi_object *buffer_desc;
	struct acpi_pld_info *pld_info;
	u8 *new_buffer;
	acpi_status status;

	/* Object must be of type Package with at least one Buffer element */

	if (obj_desc->type != ACPI_TYPE_PACKAGE) {
		return;
	}

	buffer_desc = &obj_desc->package.elements[0];
	if (buffer_desc->type != ACPI_TYPE_BUFFER) {
		return;
	}

	/* Convert _PLD buffer to local _PLD struct */

	status = acpi_decode_pld_buffer(buffer_desc->buffer.pointer,
					buffer_desc->buffer.length, &pld_info);
	if (ACPI_FAILURE(status)) {
		return;
	}

	/* Encode local _PLD struct back to a _PLD buffer */

	new_buffer = acpi_db_encode_pld_buffer(pld_info);
	if (!new_buffer) {
		goto exit;
	}

	/* The two bit-packed buffers should match */

	if (memcmp(new_buffer, buffer_desc->buffer.pointer,
		   buffer_desc->buffer.length)) {
		acpi_os_printf
		    ("Converted _PLD buffer does not compare. New:\n");

		acpi_ut_dump_buffer(new_buffer,
				    buffer_desc->buffer.length, DB_BYTE_DISPLAY,
				    0);
	}

	/* First 32-bit dword */

	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Revision", pld_info->revision);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_IgnoreColor",
		       pld_info->ignore_color);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Red", pld_info->red);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Green", pld_info->green);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Blue", pld_info->blue);

	/* Second 32-bit dword */

	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Width", pld_info->width);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Height", pld_info->height);

	/* Third 32-bit dword */

	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_UserVisible",
		       pld_info->user_visible);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Dock", pld_info->dock);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Lid", pld_info->lid);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Panel", pld_info->panel);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalPosition",
		       pld_info->vertical_position);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalPosition",
		       pld_info->horizontal_position);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Shape", pld_info->shape);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupOrientation",
		       pld_info->group_orientation);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupToken",
		       pld_info->group_token);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_GroupPosition",
		       pld_info->group_position);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Bay", pld_info->bay);

	/* Fourth 32-bit dword */

	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Ejectable", pld_info->ejectable);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_EjectRequired",
		       pld_info->ospm_eject_required);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CabinetNumber",
		       pld_info->cabinet_number);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_CardCageNumber",
		       pld_info->card_cage_number);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Reference", pld_info->reference);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Rotation", pld_info->rotation);
	acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_Order", pld_info->order);

	/* Fifth 32-bit dword */

	if (buffer_desc->buffer.length > 16) {
		acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_VerticalOffset",
			       pld_info->vertical_offset);
		acpi_os_printf(ACPI_PLD_OUTPUT, "PLD_HorizontalOffset",
			       pld_info->horizontal_offset);
	}

	ACPI_FREE(new_buffer);
exit:
	ACPI_FREE(pld_info);
}
Пример #8
0
static void
MpEmitGpioInfo (
    void)
{
    ACPI_GPIO_INFO          *Info;
    char                    *Type;
    char                    *PrevDeviceName = NULL;
    const char              *Direction;
    const char              *Polarity;
    char                    *ParentPathname;
    const char              *Description;
    char                    *HidString;
    const AH_DEVICE_ID      *HidInfo;


    /* Walk the GPIO descriptor list */

    Info = Gbl_GpioList;
    while (Info)
    {
        HidString = MpGetHidViaNamestring (Info->DeviceName);

        /* Print header info for the controller itself */

        if (!PrevDeviceName ||
            ACPI_STRCMP (PrevDeviceName, Info->DeviceName))
        {
            FlPrintFile (ASL_FILE_MAP_OUTPUT,
                "\n\nGPIO Controller:  %-8s  %-28s",
                HidString, Info->DeviceName);

            HidInfo = AcpiAhMatchHardwareId (HidString);
            if (HidInfo)
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
                    HidInfo->Description);
            }

            FlPrintFile (ASL_FILE_MAP_OUTPUT,
                "\n\nPin   Type     Direction    Polarity"
                "    Dest _HID  Destination\n");
        }

        PrevDeviceName = Info->DeviceName;

        /* Setup various strings based upon the type (GpioInt or GpioIo) */

        switch (Info->Type)
        {
        case AML_RESOURCE_GPIO_TYPE_INT:

            Type = "GpioInt";
            Direction = "-Interrupt-";
            Polarity = PolarityDecode[Info->Polarity];
            break;

        case AML_RESOURCE_GPIO_TYPE_IO:

            Type = "GpioIo ";
            Direction = DirectionDecode[Info->Direction];
            Polarity = "          ";
            break;

        default:
            continue;
        }

        /* Emit the GPIO info */

        FlPrintFile (ASL_FILE_MAP_OUTPUT, "%4.4X  %s  %s  %s  ",
            Info->PinNumber, Type, Direction, Polarity);

        ParentPathname = NULL;
        HidString = MpGetConnectionInfo (Info->Op, Info->PinIndex,
            &Info->TargetNode, &ParentPathname);
        if (HidString)
        {
            /*
             * This is a Connection() field
             * Attempt to find all references to the field.
             */
            FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
                HidString, ParentPathname);

            MpXrefDevices (Info);
        }
        else
        {
            /*
             * For Devices, attempt to get the _HID description string.
             * Failing that (many _HIDs are not recognized), attempt to
             * get the _DDN description string.
             */
            HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
                &ParentPathname);

            FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
                HidString, ParentPathname);

            /* Get the _HID description or _DDN string */

            HidInfo = AcpiAhMatchHardwareId (HidString);
            if (HidInfo)
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
                    HidInfo->Description);
            }
            else if ((Description = MpGetDdnValue (ParentPathname)))
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s (_DDN)",
                    Description);
            }
        }

        FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
        ACPI_FREE (ParentPathname);
        Info = Info->Next;
    }
}
Пример #9
0
static void
MpEmitSerialInfo (
    void)
{
    ACPI_SERIAL_INFO        *Info;
    char                    *Type;
    char                    *ParentPathname;
    char                    *PrevDeviceName = NULL;
    char                    *HidString;
    const AH_DEVICE_ID      *HidInfo;
    const char              *Description;
    AML_RESOURCE            *Resource;


    /* Walk the constructed serial descriptor list */

    Info = Gbl_SerialList;
    while (Info)
    {
        Resource = Info->Resource;
        switch (Resource->CommonSerialBus.Type)
        {
        case AML_RESOURCE_I2C_SERIALBUSTYPE:
            Type = "I2C ";
            break;

        case AML_RESOURCE_SPI_SERIALBUSTYPE:
            Type = "SPI ";
            break;

        case AML_RESOURCE_UART_SERIALBUSTYPE:
            Type = "UART";
            break;

        default:
            Type = "UNKN";
            break;
        }

        HidString = MpGetHidViaNamestring (Info->DeviceName);

        /* Print header info for the controller itself */

        if (!PrevDeviceName ||
            ACPI_STRCMP (PrevDeviceName, Info->DeviceName))
        {
            FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n%s Controller:  ",
                Type);
            FlPrintFile (ASL_FILE_MAP_OUTPUT, "%-8s  %-28s",
                HidString, Info->DeviceName);

            HidInfo = AcpiAhMatchHardwareId (HidString);
            if (HidInfo)
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
                    HidInfo->Description);
            }

            FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n\n");
            FlPrintFile (ASL_FILE_MAP_OUTPUT,
                "Type  Address   Speed      Dest _HID  Destination\n");
        }

        PrevDeviceName = Info->DeviceName;

        FlPrintFile (ASL_FILE_MAP_OUTPUT, "%s   %4.4X    %8.8X    ",
            Type, Info->Address, Info->Speed);

        ParentPathname = NULL;
        HidString = MpGetConnectionInfo (Info->Op, 0, &Info->TargetNode,
            &ParentPathname);
        if (HidString)
        {
            /*
             * This is a Connection() field
             * Attempt to find all references to the field.
             */
            FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
                HidString, ParentPathname);
        }
        else
        {
            /* Normal resource template */

            HidString = MpGetParentDeviceHid (Info->Op, &Info->TargetNode,
                &ParentPathname);
            FlPrintFile (ASL_FILE_MAP_OUTPUT, "%8s   %-28s",
                HidString, ParentPathname);

            /* Get the _HID description or _DDN string */

            HidInfo = AcpiAhMatchHardwareId (HidString);
            if (HidInfo)
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s",
                    HidInfo->Description);
            }
            else if ((Description = MpGetDdnValue (ParentPathname)))
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // %s (_DDN)",
                    Description);
            }
        }

        FlPrintFile (ASL_FILE_MAP_OUTPUT, "\n");
        ACPI_FREE (ParentPathname);
        Info = Info->Next;
    }
}
Пример #10
0
void
OptOptimizeNamePath (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Flags,
    ACPI_WALK_STATE         *WalkState,
    char                    *AmlNameString,
    ACPI_NAMESPACE_NODE     *TargetNode)
{
    ACPI_STATUS             Status;
    ACPI_BUFFER             TargetPath;
    ACPI_BUFFER             CurrentPath;
    ACPI_SIZE               AmlNameStringLength;
    ACPI_NAMESPACE_NODE     *CurrentNode;
    char                    *ExternalNameString;
    char                    *NewPath = NULL;
    ACPI_SIZE               HowMuchShorter;
    ACPI_PARSE_OBJECT       *NextOp;


    ACPI_FUNCTION_TRACE (OptOptimizeNamePath);


    /* This is an optional optimization */

    if (!Gbl_ReferenceOptimizationFlag)
    {
        return_VOID;
    }

    /* Various required items */

    if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
    {
        return_VOID;
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "%5d [%12.12s] [%12.12s] ",
        Op->Asl.LogicalLineNumber,
        AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
        AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));

    if (!(Flags & (AML_NAMED | AML_CREATE)))
    {
        if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
        {
            /* We don't want to fuss with actual name declaration nodes here */

            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
                "******* NAME DECLARATION\n"));
            return_VOID;
        }
    }

    /*
     * The original path must be longer than one NameSeg (4 chars) for there
     * to be any possibility that it can be optimized to a shorter string
     */
    AmlNameStringLength = ACPI_STRLEN (AmlNameString);
    if (AmlNameStringLength <= ACPI_NAME_SIZE)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            "NAMESEG %4.4s\n", AmlNameString));
        return_VOID;
    }

    /*
     * We need to obtain the node that represents the current scope -- where
     * we are right now in the namespace.  We will compare this path
     * against the Namepath, looking for commonality.
     */
    CurrentNode = AcpiGbl_RootNode;
    if (WalkState->ScopeInfo)
    {
        CurrentNode = WalkState->ScopeInfo->Scope.Node;
    }

    if (Flags & (AML_NAMED | AML_CREATE))
    {
        /* This is the declaration of a new name */

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME"));

        /*
         * The node of interest is the parent of this node
         * (the containing scope)
         */
        CurrentNode = Op->Asl.Parent->Asl.Node;
        if (!CurrentNode)
        {
            CurrentNode = AcpiGbl_RootNode;
        }
    }
    else
    {
        /* This is a reference to an existing named object */

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REF "));
    }

    /*
     * Obtain the full paths to the two nodes that we are interested in
     * (Target and current namespace location) in external
     * format -- something we can easily manipulate
     */
    TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    Status = AcpiNsHandleToPathname (TargetNode, &TargetPath);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }
    TargetPath.Length--;    /* Subtract one for null terminator */

    /* CurrentPath is the path to this scope (where we are in the namespace) */

    CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }
    CurrentPath.Length--;   /* Subtract one for null terminator */

    /* Debug output only */

    Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
                NULL, &ExternalNameString);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
            ASL_NO_ABORT);
        return_VOID;
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
        "%37s (%2u) ==> %-32s(%2u) %-32s",
        (char *) CurrentPath.Pointer, (UINT32) CurrentPath.Length,
        (char *) TargetPath.Pointer, (UINT32) TargetPath.Length, ExternalNameString));

    ACPI_FREE (ExternalNameString);

    /*
     * Attempt an optmization depending on the type of namepath
     */
    if (Flags & (AML_NAMED | AML_CREATE))
    {
        /*
         * This is a named opcode and the namepath is a name declaration, not
         * a reference.
         */
        Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
                    TargetNode, AmlNameString, &NewPath);
        if (ACPI_FAILURE (Status))
        {
            /*
             * 2) now attempt to
             *    optimize the namestring with carats (up-arrow)
             */
            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
                            TargetNode, &CurrentPath, &TargetPath,
                            AmlNameStringLength, 1, &NewPath);
        }
    }
    else
    {
        /*
         * This is a reference to an existing named object
         *
         * 1) Check if search-to-root can be utilized using the last
         *    NameSeg of the NamePath
         */
        Status = OptSearchToRoot (Op, WalkState, CurrentNode,
                        TargetNode, &TargetPath, &NewPath);
        if (ACPI_FAILURE (Status))
        {
            /*
             * 2) Search-to-root could not be used, now attempt to
             *    optimize the namestring with carats (up-arrow)
             */
            Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
                            TargetNode, &CurrentPath, &TargetPath,
                            AmlNameStringLength, 0, &NewPath);
        }
    }

    /*
     * Success from above indicates that the NamePath was successfully
     * optimized.  We need to update the parse op with the new name
     */
    if (ACPI_SUCCESS (Status))
    {
        HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath));
        OptTotal += HowMuchShorter;

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " REDUCED %2u (%u)",
            (UINT32) HowMuchShorter, OptTotal));

        if (Flags & AML_NAMED)
        {
            if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
            {
                /*
                 * ALIAS is the only oddball opcode, the name declaration
                 * (alias name) is the second operand
                 */
                Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
                Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath);
            }
            else
            {
                Op->Asl.Child->Asl.Value.String = NewPath;
                Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath);
            }
        }
        else if (Flags & AML_CREATE)
        {
            /* Name must appear as the last parameter */

            NextOp = Op->Asl.Child;
            while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
            {
                NextOp = NextOp->Asl.Next;
            }
            /* Update the parse node with the new NamePath */

            NextOp->Asl.Value.String = NewPath;
            NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath);
        }
        else
        {
            /* Update the parse node with the new NamePath */

            Op->Asl.Value.String = NewPath;
            Op->Asl.AmlLength = ACPI_STRLEN (NewPath);
        }
    }
    else
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
    }

    /* Cleanup path buffers */

    ACPI_FREE (TargetPath.Pointer);
    ACPI_FREE (CurrentPath.Pointer);

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
    return_VOID;
}
Пример #11
0
void
AcpiDsDeleteWalkState (
    ACPI_WALK_STATE         *WalkState)
{
    ACPI_GENERIC_STATE      *State;


    ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState);


    if (!WalkState)
    {
        return_VOID;
    }

    if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK)
    {
        ACPI_ERROR ((AE_INFO, "%p is not a valid walk state",
            WalkState));
        return_VOID;
    }

    /* There should not be any open scopes */

    if (WalkState->ParserState.Scope)
    {
        ACPI_ERROR ((AE_INFO, "%p walk still has a scope list",
            WalkState));
        AcpiPsCleanupScope (&WalkState->ParserState);
    }

    /* Always must free any linked control states */

    while (WalkState->ControlState)
    {
        State = WalkState->ControlState;
        WalkState->ControlState = State->Common.Next;

        AcpiUtDeleteGenericState (State);
    }

    /* Always must free any linked parse states */

    while (WalkState->ScopeInfo)
    {
        State = WalkState->ScopeInfo;
        WalkState->ScopeInfo = State->Common.Next;

        AcpiUtDeleteGenericState (State);
    }

    /* Always must free any stacked result states */

    while (WalkState->Results)
    {
        State = WalkState->Results;
        WalkState->Results = State->Common.Next;

        AcpiUtDeleteGenericState (State);
    }

    ACPI_FREE (WalkState);
    return_VOID;
}
Пример #12
0
static ACPI_STATUS
OptOptimizeNameDeclaration (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *CurrentNode,
    ACPI_NAMESPACE_NODE     *TargetNode,
    char                    *AmlNameString,
    char                    **NewPath)
{
    ACPI_STATUS             Status;
    char                    *NewPathExternal;
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_NAMESPACE_NODE     *Node;


    ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration);


    if (((CurrentNode == AcpiGbl_RootNode) ||
        (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
            (AmlNameString[0] == '\\'))
    {
        /*
         * The current scope is the root, and the namepath has a root prefix
         * that is therefore extraneous.  Remove it.
         */
        *NewPath = &AmlNameString[1];

        /* Debug output */

        Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
                    NULL, &NewPathExternal);
        if (ACPI_FAILURE (Status))
        {
            AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
                ASL_NO_ABORT);
            return (Status);
        }

        /*
         * Check to make sure that the optimization finds the node we are
         * looking for.  This is simply a sanity check on the new
         * path that has been created.
         */
        ScopeInfo.Scope.Node = CurrentNode;
        Status = AcpiNsLookup (&ScopeInfo, *NewPath,
                        ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                        ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
        if (ACPI_SUCCESS (Status))
        {
            /* Found the namepath, but make sure the node is correct */

            if (Node == TargetNode)
            {
                /* The lookup matched the node, accept this optimization */

                AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
                    Op, NewPathExternal);

                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
                    "AT ROOT:   %-24s", NewPathExternal));
            }
            else
            {
                /* Node is not correct, do not use this optimization */

                Status = AE_NOT_FOUND;
                ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
                    " ***** WRONG NODE"));
                AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
                    "Not using optimized name - found wrong node");
            }
        }
        else
        {
            /* The lookup failed, we obviously cannot use this optimization */

            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
                " ***** NOT FOUND"));
            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
                "Not using optimized name - did not find node");
        }

        ACPI_FREE (NewPathExternal);
        return (Status);
    }

    /* Could not optimize */

    return (AE_NOT_FOUND);
}
Пример #13
0
static ACPI_STATUS
OptBuildShortestPath (
    ACPI_PARSE_OBJECT       *Op,
    ACPI_WALK_STATE         *WalkState,
    ACPI_NAMESPACE_NODE     *CurrentNode,
    ACPI_NAMESPACE_NODE     *TargetNode,
    ACPI_BUFFER             *CurrentPath,
    ACPI_BUFFER             *TargetPath,
    ACPI_SIZE               AmlNameStringLength,
    UINT8                   IsDeclaration,
    char                    **ReturnNewPath)
{
    UINT32                  NumCommonSegments;
    UINT32                  MaxCommonSegments;
    UINT32                  Index;
    UINT32                  NumCarats;
    UINT32                  i;
    char                    *NewPath;
    char                    *NewPathExternal;
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_STATUS             Status;
    BOOLEAN                 SubPath = FALSE;


    ACPI_FUNCTION_NAME (OptBuildShortestPath);


    ScopeInfo.Scope.Node = CurrentNode;

    /*
     * Determine the maximum number of NameSegs that the Target and Current paths
     * can possibly have in common.  (To optimize, we have to have at least 1)
     *
     * Note: The external NamePath string lengths are always a multiple of 5
     * (ACPI_NAME_SIZE + separator)
     */
    MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    if (CurrentPath->Length < TargetPath->Length)
    {
        MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
    }

    /*
     * Determine how many NameSegs the two paths have in common.
     * (Starting from the root)
     */
    for (NumCommonSegments = 0;
         NumCommonSegments < MaxCommonSegments;
         NumCommonSegments++)
    {
        /* Compare two single NameSegs */

        if (ACPI_STRNCMP (
            &((char *) TargetPath->Pointer)[(NumCommonSegments *
                                             ACPI_PATH_SEGMENT_LENGTH) + 1],
            &((char *) CurrentPath->Pointer)[(NumCommonSegments *
                                              ACPI_PATH_SEGMENT_LENGTH) + 1],
            ACPI_NAME_SIZE))
        {
            /* Mismatch */

            break;
        }
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
        NumCommonSegments));

    /* There must be at least 1 common NameSeg in order to optimize */

    if (NumCommonSegments == 0)
    {
        return (AE_NOT_FOUND);
    }

    if (NumCommonSegments == MaxCommonSegments)
    {
        if (CurrentPath->Length == TargetPath->Length)
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
            return (AE_NOT_FOUND);
        }
        else
        {
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
            SubPath = TRUE;
        }
    }

    /* Determine how many prefix Carats are required */

    NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
                NumCommonSegments;

    /*
     * Construct a new target string
     */
    NewPathExternal = ACPI_ALLOCATE_ZEROED (
        TargetPath->Length + NumCarats + 1);

    /* Insert the Carats into the Target string */

    for (i = 0; i < NumCarats; i++)
    {
        NewPathExternal[i] = '^';
    }

    /*
     * Copy only the necessary (optimal) segments from the original
     * target string
     */
    Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;

    /* Special handling for exact subpath in a name declaration */

    if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
    {
        /*
         * The current path is longer than the target, and the target is a
         * subpath of the current path. We must include one more NameSeg of
         * the target path
         */
        Index -= ACPI_PATH_SEGMENT_LENGTH;

        /* Special handling for Scope() operator */

        if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
        {
            NewPathExternal[i] = '^';
            i++;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
        }
    }

    /* Make sure we haven't gone off the end of the target path */

    if (Index > TargetPath->Length)
    {
        Index = TargetPath->Length;
    }

    ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));

    /*
     * Internalize the new target string and check it against the original
     * string to make sure that this is in fact an optimization. If the
     * original string is already optimal, there is no point in continuing.
     */
    Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
    if (ACPI_FAILURE (Status))
    {
        AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
            ASL_NO_ABORT);
        ACPI_FREE (NewPathExternal);
        return (Status);
    }

    if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
    {
        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
            " NOT SHORTER (New %u old %u)",
            (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength));
        ACPI_FREE (NewPathExternal);
        return (AE_NOT_FOUND);
    }

    /*
     * Check to make sure that the optimization finds the node we are
     * looking for.  This is simply a sanity check on the new
     * path that has been created.
     */
    Status = AcpiNsLookup (&ScopeInfo,  NewPath,
                    ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
                    ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
    if (ACPI_SUCCESS (Status))
    {
        /* Found the namepath, but make sure the node is correct */

        if (Node == TargetNode)
        {
            /* The lookup matched the node, accept this optimization */

            AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
                Op, NewPathExternal);
            *ReturnNewPath = NewPath;
        }
        else
        {
            /* Node is not correct, do not use this optimization */

            Status = AE_NOT_FOUND;
            ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
            AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
                "Not using optimized name - found wrong node");
        }
    }
    else
    {
        /* The lookup failed, we obviously cannot use this optimization */

        ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
        AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
            "Not using optimized name - did not find node");
    }

    ACPI_FREE (NewPathExternal);
    return (Status);
}
Пример #14
0
void
AdCreateTableHeader (
    char                    *Filename,
    ACPI_TABLE_HEADER       *Table)
{
    char                    *NewFilename;
    UINT8                   Checksum;


    /*
     * Print file header and dump original table header
     */
    AdDisassemblerHeader (Filename);

    AcpiOsPrintf (" *\n * Original Table Header:\n");
    AcpiOsPrintf (" *     Signature        \"%4.4s\"\n",    Table->Signature);
    AcpiOsPrintf (" *     Length           0x%8.8X (%u)\n", Table->Length, Table->Length);

    /* Print and validate the revision */

    AcpiOsPrintf (" *     Revision         0x%2.2X",      Table->Revision);

    switch (Table->Revision)
    {
    case 0:
        AcpiOsPrintf (" **** Invalid Revision");
        break;

    case 1:
        /* Revision of DSDT controls the ACPI integer width */

        if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT))
        {
            AcpiOsPrintf (" **** ACPI 1.0, no 64-bit math support");
        }
        break;

    default:
        break;
    }
    AcpiOsPrintf ("\n");

    /* Print and validate the table checksum */

    AcpiOsPrintf (" *     Checksum         0x%2.2X",        Table->Checksum);

    Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Table->Length);
    if (Checksum)
    {
        AcpiOsPrintf (" **** Incorrect checksum, should be 0x%2.2X",
            (UINT8) (Table->Checksum - Checksum));
    }
    AcpiOsPrintf ("\n");

    AcpiOsPrintf (" *     OEM ID           \"%.6s\"\n",     Table->OemId);
    AcpiOsPrintf (" *     OEM Table ID     \"%.8s\"\n",     Table->OemTableId);
    AcpiOsPrintf (" *     OEM Revision     0x%8.8X (%u)\n", Table->OemRevision, Table->OemRevision);
    AcpiOsPrintf (" *     Compiler ID      \"%.4s\"\n",     Table->AslCompilerId);
    AcpiOsPrintf (" *     Compiler Version 0x%8.8X (%u)\n", Table->AslCompilerRevision, Table->AslCompilerRevision);
    AcpiOsPrintf (" */\n");

    /* Create AML output filename based on input filename */

    if (Filename)
    {
        NewFilename = FlGenerateFilename (Filename, "aml");
    }
    else
    {
        NewFilename = ACPI_ALLOCATE_ZEROED (9);
        strncat (NewFilename, Table->Signature, 4);
        strcat (NewFilename, ".aml");
    }

    /* Open the ASL definition block */

    AcpiOsPrintf (
        "DefinitionBlock (\"%s\", \"%4.4s\", %hd, \"%.6s\", \"%.8s\", 0x%8.8X)\n",
        NewFilename, Table->Signature, Table->Revision,
        Table->OemId, Table->OemTableId, Table->OemRevision);

    ACPI_FREE (NewFilename);
}
Пример #15
0
static void
LsWriteNodeToListing (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  FileId)
{
    const ACPI_OPCODE_INFO  *OpInfo;
    UINT32                  OpClass;
    char                    *Pathname;
    UINT32                  Length;
    UINT32                  i;


    OpInfo  = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);
    OpClass = OpInfo->Class;

    /* TBD: clean this up with a single flag that says:
     * I start a named output block
     */
    if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
    {
        switch (Op->Asl.ParseOpcode)
        {
        case PARSEOP_DEFINITIONBLOCK:
        case PARSEOP_METHODCALL:
        case PARSEOP_INCLUDE:
        case PARSEOP_INCLUDE_END:
        case PARSEOP_DEFAULT_ARG:

            break;

        default:

            switch (OpClass)
            {
            case AML_CLASS_NAMED_OBJECT:

                switch (Op->Asl.AmlOpcode)
                {
                case AML_SCOPE_OP:
                case AML_ALIAS_OP:

                    break;

                default:

                    if (Op->Asl.ExternalName)
                    {
                        LsFlushListingBuffer (FileId);
                        FlPrintFile (FileId, "    };\n");
                    }
                    break;
                }
                break;

            default:

                /* Don't care about other objects */

                break;
            }
            break;
        }
    }

    /* These cases do not have a corresponding AML opcode */

    switch (Op->Asl.ParseOpcode)
    {
    case PARSEOP_DEFINITIONBLOCK:

        LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine, FileId);

        /* Use the table Signature and TableId to build a unique name */

        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
        {
            FlPrintFile (FileId,
                "%s_%s_Header \\\n",
                Gbl_TableSignature, Gbl_TableId);
        }
        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
        {
            FlPrintFile (FileId,
                "    unsigned char    %s_%s_Header [] =\n    {\n",
                Gbl_TableSignature, Gbl_TableId);
        }
        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
        {
            FlPrintFile (FileId,
                "extrn %s_%s_Header : byte\n",
                Gbl_TableSignature, Gbl_TableId);
        }
        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
        {
            FlPrintFile (FileId,
                "extern unsigned char    %s_%s_Header [];\n",
                Gbl_TableSignature, Gbl_TableId);
        }
        return;


    case PARSEOP_METHODCALL:

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);
        return;


    case PARSEOP_INCLUDE:

        /* Flush everything up to and including the include source line */

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);

        /* Create a new listing node and push it */

        LsPushNode (Op->Asl.Child->Asl.Value.String);
        return;


    case PARSEOP_INCLUDE_END:

        /* Flush out the rest of the include file */

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);

        /* Pop off this listing node and go back to the parent file */

        (void) LsPopNode ();
        return;


    case PARSEOP_DEFAULT_ARG:

        if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
        {
            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.EndLogicalLine,
                FileId);
        }
        return;


    default:

        /* All other opcodes have an AML opcode */

        break;
    }

    /*
     * Otherwise, we look at the AML opcode because we can
     * switch on the opcode type, getting an entire class
     * at once
     */
    switch (OpClass)
    {
    case AML_CLASS_ARGUMENT:       /* argument type only */
    case AML_CLASS_INTERNAL:

        break;

    case AML_CLASS_NAMED_OBJECT:

        switch (Op->Asl.AmlOpcode)
        {
        case AML_FIELD_OP:
        case AML_INDEX_FIELD_OP:
        case AML_BANK_FIELD_OP:
            /*
             * For fields, we want to dump all the AML after the
             * entire definition
             */
            LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
                FileId);
            break;

        case AML_NAME_OP:

            if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC)
            {
                LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
                    FileId);
            }
            else
            {
                /*
                 * For fields, we want to dump all the AML after the
                 * entire definition
                 */
                LsWriteSourceLines (Op->Asl.EndLine, Op->Asl.EndLogicalLine,
                    FileId);
            }
            break;

        default:

            LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
                FileId);
            break;
        }

        switch (Op->Asl.AmlOpcode)
        {
        case AML_SCOPE_OP:
        case AML_ALIAS_OP:

            /* These opcodes do not declare a new object, ignore them */

            break;

        default:

            /* All other named object opcodes come here */

            switch (FileId)
            {
            case ASL_FILE_ASM_SOURCE_OUTPUT:
            case ASL_FILE_C_SOURCE_OUTPUT:
            case ASL_FILE_ASM_INCLUDE_OUTPUT:
            case ASL_FILE_C_INCLUDE_OUTPUT:
                /*
                 * For named objects, we will create a valid symbol so that the
                 * AML code can be referenced from C or ASM
                 */
                if (Op->Asl.ExternalName)
                {
                    /* Get the full pathname associated with this node */

                    Pathname = AcpiNsGetExternalPathname (Op->Asl.Node);
                    Length = strlen (Pathname);
                    if (Length >= 4)
                    {
                        /* Convert all dots in the path to underscores */

                        for (i = 0; i < Length; i++)
                        {
                            if (Pathname[i] == '.')
                            {
                                Pathname[i] = '_';
                            }
                        }

                        /* Create the appropriate symbol in the output file */

                        if (FileId == ASL_FILE_ASM_SOURCE_OUTPUT)
                        {
                            FlPrintFile (FileId,
                                "%s_%s_%s  \\\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                        }
                        if (FileId == ASL_FILE_C_SOURCE_OUTPUT)
                        {
                            FlPrintFile (FileId,
                                "    unsigned char    %s_%s_%s [] =\n    {\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                        }
                        if (FileId == ASL_FILE_ASM_INCLUDE_OUTPUT)
                        {
                            FlPrintFile (FileId,
                                "extrn %s_%s_%s : byte\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                        }
                        if (FileId == ASL_FILE_C_INCLUDE_OUTPUT)
                        {
                            FlPrintFile (FileId,
                                "extern unsigned char    %s_%s_%s [];\n",
                                Gbl_TableSignature, Gbl_TableId, &Pathname[1]);
                        }
                    }
                    ACPI_FREE (Pathname);
                }
                break;

            default:

                /* Nothing to do for listing file */

                break;
            }
        }
        break;

    case AML_CLASS_EXECUTE:
    case AML_CLASS_CREATE:
    default:

        if ((Op->Asl.ParseOpcode == PARSEOP_BUFFER) &&
            (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC))
        {
            return;
        }

        LsWriteSourceLines (Op->Asl.LineNumber, Op->Asl.LogicalLineNumber,
            FileId);
        break;

    case AML_CLASS_UNKNOWN:

        break;
    }
}
Пример #16
0
static ACPI_STATUS
MpNamespaceXrefBegin (
    ACPI_PARSE_OBJECT       *Op,
    UINT32                  Level,
    void                    *Context)
{
    ACPI_GPIO_INFO          *Info = ACPI_CAST_PTR (ACPI_GPIO_INFO, Context);
    const ACPI_OPCODE_INFO  *OpInfo;
    char                    *DevicePathname;
    ACPI_PARSE_OBJECT       *ParentOp;
    char                    *HidString;


    ACPI_FUNCTION_TRACE_PTR (MpNamespaceXrefBegin, Op);

    /*
     * If this node is the actual declaration of a name
     * [such as the XXXX name in "Method (XXXX)"],
     * we are not interested in it here. We only care about names that
     * are references to other objects within the namespace and the
     * parent objects of name declarations
     */
    if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
    {
        return (AE_OK);
    }

    /* We are only interested in opcodes that have an associated name */

    OpInfo = AcpiPsGetOpcodeInfo (Op->Asl.AmlOpcode);

    if ((OpInfo->Flags & AML_NAMED) ||
        (OpInfo->Flags & AML_CREATE))
    {
        return (AE_OK);
    }

    if ((Op->Asl.ParseOpcode != PARSEOP_NAMESTRING) &&
        (Op->Asl.ParseOpcode != PARSEOP_NAMESEG)    &&
        (Op->Asl.ParseOpcode != PARSEOP_METHODCALL))
    {
        return (AE_OK);
    }

    if (!Op->Asl.Node)
    {
        return (AE_OK);
    }

    ParentOp = Op->Asl.Parent;
    if (ParentOp->Asl.ParseOpcode == PARSEOP_FIELD)
    {
        return (AE_OK);
    }

    if (Op->Asl.Node == Info->TargetNode)
    {
        while (ParentOp && (!ParentOp->Asl.Node))
        {
            ParentOp = ParentOp->Asl.Parent;
        }

        if (ParentOp)
        {
            DevicePathname = AcpiNsGetExternalPathname (
                ParentOp->Asl.Node);

            if (!Info->References)
            {
                FlPrintFile (ASL_FILE_MAP_OUTPUT, "  // References:");
            }

            HidString = MpGetHidViaNamestring (DevicePathname);

            FlPrintFile (ASL_FILE_MAP_OUTPUT, " %s [%s]",
                DevicePathname, HidString);

            Info->References++;

            ACPI_FREE (DevicePathname);
        }
    }

    return (AE_OK);
}
Пример #17
0
ACPI_STATUS
AcpiEvaluateObject (
    ACPI_HANDLE             Handle,
    ACPI_CONST_STRING       Pathname,
    ACPI_OBJECT_LIST        *ExternalParams,
    ACPI_BUFFER             *ReturnBuffer)
{
    ACPI_STATUS             Status;
    ACPI_EVALUATE_INFO      *Info;
    ACPI_SIZE               BufferSpaceNeeded;
    UINT32                  i;


    ACPI_FUNCTION_TRACE (AcpiEvaluateObject);


    /* Allocate and initialize the evaluation information block */

    Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    Info->Pathname = Pathname;
    Info->ParameterType = ACPI_PARAM_ARGS;

    /* Convert and validate the device handle */

    Info->PrefixNode = AcpiNsMapHandleToNode (Handle);
    if (!Info->PrefixNode)
    {
        Status = AE_BAD_PARAMETER;
        goto Cleanup;
    }

    /*
     * If there are parameters to be passed to a control method, the external
     * objects must all be converted to internal objects
     */
    if (ExternalParams && ExternalParams->Count)
    {
        /*
         * Allocate a new parameter block for the internal objects
         * Add 1 to count to allow for null terminated internal list
         */
        Info->Parameters = ACPI_ALLOCATE_ZEROED (
            ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *));
        if (!Info->Parameters)
        {
            Status = AE_NO_MEMORY;
            goto Cleanup;
        }

        /* Convert each external object in the list to an internal object */

        for (i = 0; i < ExternalParams->Count; i++)
        {
            Status = AcpiUtCopyEobjectToIobject (
                        &ExternalParams->Pointer[i], &Info->Parameters[i]);
            if (ACPI_FAILURE (Status))
            {
                goto Cleanup;
            }
        }
        Info->Parameters[ExternalParams->Count] = NULL;
    }

    /*
     * Three major cases:
     * 1) Fully qualified pathname
     * 2) No handle, not fully qualified pathname (error)
     * 3) Valid handle
     */
    if ((Pathname) &&
        (AcpiNsValidRootPrefix (Pathname[0])))
    {
        /* The path is fully qualified, just evaluate by name */

        Info->PrefixNode = NULL;
        Status = AcpiNsEvaluate (Info);
    }
    else if (!Handle)
    {
        /*
         * A handle is optional iff a fully qualified pathname is specified.
         * Since we've already handled fully qualified names above, this is
         * an error
         */
        if (!Pathname)
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Both Handle and Pathname are NULL"));
        }
        else
        {
            ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                "Null Handle with relative pathname [%s]", Pathname));
        }

        Status = AE_BAD_PARAMETER;
    }
    else
    {
        /* We have a namespace a node and a possible relative path */

        Status = AcpiNsEvaluate (Info);
    }

    /*
     * If we are expecting a return value, and all went well above,
     * copy the return value to an external object.
     */
    if (ReturnBuffer)
    {
        if (!Info->ReturnObject)
        {
            ReturnBuffer->Length = 0;
        }
        else
        {
            if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
                ACPI_DESC_TYPE_NAMED)
            {
                /*
                 * If we received a NS Node as a return object, this means that
                 * the object we are evaluating has nothing interesting to
                 * return (such as a mutex, etc.)  We return an error because
                 * these types are essentially unsupported by this interface.
                 * We don't check up front because this makes it easier to add
                 * support for various types at a later date if necessary.
                 */
                Status = AE_TYPE;
                Info->ReturnObject = NULL;   /* No need to delete a NS Node */
                ReturnBuffer->Length = 0;
            }

            if (ACPI_SUCCESS (Status))
            {
                /* Get the size of the returned object */

                Status = AcpiUtGetObjectSize (Info->ReturnObject,
                            &BufferSpaceNeeded);
                if (ACPI_SUCCESS (Status))
                {
                    /* Validate/Allocate/Clear caller buffer */

                    Status = AcpiUtInitializeBuffer (ReturnBuffer,
                                BufferSpaceNeeded);
                    if (ACPI_FAILURE (Status))
                    {
                        /*
                         * Caller's buffer is too small or a new one can't
                         * be allocated
                         */
                        ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
                            "Needed buffer size %X, %s\n",
                            (UINT32) BufferSpaceNeeded,
                            AcpiFormatException (Status)));
                    }
                    else
                    {
                        /* We have enough space for the object, build it */

                        Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
                                    ReturnBuffer);
                    }
                }
            }
        }
    }

    if (Info->ReturnObject)
    {
        /*
         * Delete the internal return object. NOTE: Interpreter must be
         * locked to avoid race condition.
         */
        AcpiExEnterInterpreter ();

        /* Remove one reference on the return object (should delete it) */

        AcpiUtRemoveReference (Info->ReturnObject);
        AcpiExExitInterpreter ();
    }


Cleanup:

    /* Free the input parameter list (if we created one) */

    if (Info->Parameters)
    {
        /* Free the allocated parameter block */

        AcpiUtDeleteInternalObjectList (Info->Parameters);
    }

    ACPI_FREE (Info);
    return_ACPI_STATUS (Status);
}
/*******************************************************************************
 *
 * FUNCTION:    ns_execute_table
 *
 * PARAMETERS:  table_desc      - An ACPI table descriptor for table to parse
 *              start_node      - Where to enter the table into the namespace
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Load ACPI/AML table by executing the entire table as a
 *              term_list.
 *
 ******************************************************************************/
acpi_status
acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
{
	acpi_status status;
	struct acpi_table_header *table;
	acpi_owner_id owner_id;
	struct acpi_evaluate_info *info = NULL;
	u32 aml_length;
	u8 *aml_start;
	union acpi_operand_object *method_obj = NULL;

	ACPI_FUNCTION_TRACE(ns_execute_table);

	status = acpi_get_table_by_index(table_index, &table);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Table must consist of at least a complete header */

	if (table->length < sizeof(struct acpi_table_header)) {
		return_ACPI_STATUS(AE_BAD_HEADER);
	}

	aml_start = (u8 *)table + sizeof(struct acpi_table_header);
	aml_length = table->length - sizeof(struct acpi_table_header);

	status = acpi_tb_get_owner_id(table_index, &owner_id);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Create, initialize, and link a new temporary method object */

	method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
	if (!method_obj) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Allocate the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
			  "Create table code block: %p\n", method_obj));

	method_obj->method.aml_start = aml_start;
	method_obj->method.aml_length = aml_length;
	method_obj->method.owner_id = owner_id;
	method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;

	info->pass_number = ACPI_IMODE_EXECUTE;
	info->node = start_node;
	info->obj_desc = method_obj;
	info->node_flags = info->node->flags;
	info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
	if (!info->full_pathname) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	status = acpi_ps_execute_table(info);

cleanup:
	if (info) {
		ACPI_FREE(info->full_pathname);
		info->full_pathname = NULL;
	}
	ACPI_FREE(info);
	acpi_ut_remove_reference(method_obj);
	return_ACPI_STATUS(status);
}
Пример #19
0
ACPI_STATUS
AcpiNsGetNode (
    ACPI_NAMESPACE_NODE     *PrefixNode,
    const char              *Pathname,
    UINT32                  Flags,
    ACPI_NAMESPACE_NODE     **ReturnNode)
{
    ACPI_GENERIC_STATE      ScopeInfo;
    ACPI_STATUS             Status;
    char                    *InternalPath;


    ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname));


    if (!Pathname)
    {
        *ReturnNode = PrefixNode;
        if (!PrefixNode)
        {
            *ReturnNode = AcpiGbl_RootNode;
        }
        return_ACPI_STATUS (AE_OK);
    }

    /* Convert path to internal representation */

    Status = AcpiNsInternalizeName (Pathname, &InternalPath);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Must lock namespace during lookup */

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

    /* Setup lookup scope (search starting point) */

    ScopeInfo.Scope.Node = PrefixNode;

    /* Lookup the name in the namespace */

    Status = AcpiNsLookup (&ScopeInfo, InternalPath, ACPI_TYPE_ANY,
                ACPI_IMODE_EXECUTE, (Flags | ACPI_NS_DONT_OPEN_SCOPE),
                NULL, ReturnNode);
    if (ACPI_FAILURE (Status))
    {
        ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s, %s\n",
                Pathname, AcpiFormatException (Status)));
    }

    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);

Cleanup:
    ACPI_FREE (InternalPath);
    return_ACPI_STATUS (Status);
}
Пример #20
0
ACPI_STATUS
DtCompileTable (
    DT_FIELD                **Field,
    ACPI_DMTABLE_INFO       *Info,
    DT_SUBTABLE             **RetSubtable,
    BOOLEAN                 Required)
{
    DT_FIELD                *LocalField;
    UINT32                  Length;
    DT_SUBTABLE             *Subtable;
    DT_SUBTABLE             *InlineSubtable = NULL;
    UINT32                  FieldLength = 0;
    UINT8                   FieldType;
    UINT8                   *Buffer;
    UINT8                   *FlagBuffer = NULL;
    char                    *String;
    UINT32                  CurrentFlagByteOffset = 0;
    ACPI_STATUS             Status = AE_OK;


    if (!Field || !*Field)
    {
        return (AE_BAD_PARAMETER);
    }

    /* Ignore optional subtable if name does not match */

    if ((Info->Flags & DT_OPTIONAL) &&
        ACPI_STRCMP ((*Field)->Name, Info->Name))
    {
        *RetSubtable = NULL;
        return (AE_OK);
    }

    Length = DtGetSubtableLength (*Field, Info);
    if (Length == ASL_EOF)
    {
        return (AE_ERROR);
    }

    Subtable = UtSubtableCacheCalloc ();

    if (Length > 0)
    {
        String = UtStringCacheCalloc (Length);
        Subtable->Buffer = ACPI_CAST_PTR (UINT8, String);
    }

    Subtable->Length = Length;
    Subtable->TotalLength = Length;
    Buffer = Subtable->Buffer;

    LocalField = *Field;

    /*
     * Main loop walks the info table for this ACPI table or subtable
     */
    for (; Info->Name; Info++)
    {
        if (Info->Opcode == ACPI_DMT_EXTRA_TEXT)
        {
            continue;
        }

        if (!LocalField)
        {
            sprintf (MsgBuffer, "Found NULL field - Field name \"%s\" needed",
                Info->Name);
            DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
            Status = AE_BAD_DATA;
            goto Error;
        }

        /* Maintain table offsets */

        LocalField->TableOffset = Gbl_CurrentTableOffset;
        FieldLength = DtGetFieldLength (LocalField, Info);
        Gbl_CurrentTableOffset += FieldLength;

        FieldType = DtGetFieldType (Info);
        Gbl_InputFieldCount++;

        switch (FieldType)
        {
        case DT_FIELD_TYPE_FLAGS_INTEGER:
            /*
             * Start of the definition of a flags field.
             * This master flags integer starts at value zero, in preparation
             * to compile and insert the flag fields from the individual bits
             */
            LocalField = LocalField->Next;
            *Field = LocalField;

            FlagBuffer = Buffer;
            CurrentFlagByteOffset = Info->Offset;
            break;

        case DT_FIELD_TYPE_FLAG:

            /* Individual Flag field, can be multiple bits */

            if (FlagBuffer)
            {
                /*
                 * We must increment the FlagBuffer when we have crossed
                 * into the next flags byte within the flags field
                 * of type DT_FIELD_TYPE_FLAGS_INTEGER.
                 */
                FlagBuffer += (Info->Offset - CurrentFlagByteOffset);
                CurrentFlagByteOffset = Info->Offset;

                DtCompileFlag (FlagBuffer, LocalField, Info);
            }
            else
            {
                /* TBD - this is an internal error */
            }

            LocalField = LocalField->Next;
            *Field = LocalField;
            break;

        case DT_FIELD_TYPE_INLINE_SUBTABLE:
            /*
             * Recursion (one level max): compile GAS (Generic Address)
             * or Notify in-line subtable
             */
            *Field = LocalField;

            switch (Info->Opcode)
            {
            case ACPI_DMT_GAS:

                Status = DtCompileTable (Field, AcpiDmTableInfoGas,
                    &InlineSubtable, TRUE);
                break;

            case ACPI_DMT_HESTNTFY:

                Status = DtCompileTable (Field, AcpiDmTableInfoHestNotify,
                    &InlineSubtable, TRUE);
                break;

            case ACPI_DMT_IORTMEM:

                Status = DtCompileTable (Field, AcpiDmTableInfoIortAcc,
                    &InlineSubtable, TRUE);
                break;

            default:
                sprintf (MsgBuffer, "Invalid DMT opcode: 0x%.2X",
                    Info->Opcode);
                DtFatal (ASL_MSG_COMPILER_INTERNAL, NULL, MsgBuffer);
                Status = AE_BAD_DATA;
                break;
            }

            if (ACPI_FAILURE (Status))
            {
                goto Error;
            }

            DtSetSubtableLength (InlineSubtable);

            ACPI_MEMCPY (Buffer, InlineSubtable->Buffer, FieldLength);
            LocalField = *Field;
            break;

        case DT_FIELD_TYPE_LABEL:

            DtWriteFieldToListing (Buffer, LocalField, 0);
            LocalField = LocalField->Next;
            break;

        default:

            /* Normal case for most field types (Integer, String, etc.) */

            DtCompileOneField (Buffer, LocalField,
                FieldLength, FieldType, Info->Flags);

            DtWriteFieldToListing (Buffer, LocalField, FieldLength);
            LocalField = LocalField->Next;

            if (Info->Flags & DT_LENGTH)
            {
                /* Field is an Integer that will contain a subtable length */

                Subtable->LengthField = Buffer;
                Subtable->SizeOfLengthField = FieldLength;
            }

            break;
        }

        Buffer += FieldLength;
    }

    *Field = LocalField;
    *RetSubtable = Subtable;
    return (AE_OK);

Error:
    ACPI_FREE (Subtable->Buffer);
    ACPI_FREE (Subtable);
    return (Status);
}
Пример #21
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
         */
        memset (TargetDesc->String.Pointer, 0,
            (ACPI_SIZE) TargetDesc->String.Length + 1);
        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;
        memcpy (TargetDesc->String.Pointer, Buffer, Length);
    }

    /* Set the new target length */

    TargetDesc->String.Length = Length;
    return_ACPI_STATUS (AE_OK);
}
Пример #22
0
acpi_status
acpi_ds_call_control_method(struct acpi_thread_state *thread,
			    struct acpi_walk_state *this_walk_state,
			    union acpi_parse_object *op)
{
	acpi_status status;
	struct acpi_namespace_node *method_node;
	struct acpi_walk_state *next_walk_state = NULL;
	union acpi_operand_object *obj_desc;
	struct acpi_evaluate_info *info;
	u32 i;

	ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state);

	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
			  "Calling method %p, currentstate=%p\n",
			  this_walk_state->prev_op, this_walk_state));

	/*
	 * Get the namespace entry for the control method we are about to call
	 */
	method_node = this_walk_state->method_call_node;
	if (!method_node) {
		return_ACPI_STATUS(AE_NULL_ENTRY);
	}

	obj_desc = acpi_ns_get_attached_object(method_node);
	if (!obj_desc) {
		return_ACPI_STATUS(AE_NULL_OBJECT);
	}

	/* Init for new method, possibly wait on method mutex */

	status = acpi_ds_begin_method_execution(method_node, obj_desc,
						this_walk_state);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
	}

	/* Begin method parse/execution. Create a new walk state */

	next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id,
						    NULL, obj_desc, thread);
	if (!next_walk_state) {
		status = AE_NO_MEMORY;
		goto cleanup;
	}

	/*
	 * The resolved arguments were put on the previous walk state's operand
	 * stack. Operands on the previous walk state stack always
	 * start at index 0. Also, null terminate the list of arguments
	 */
	this_walk_state->operands[this_walk_state->num_operands] = NULL;

	/*
	 * Allocate and initialize the evaluation information block
	 * TBD: this is somewhat inefficient, should change interface to
	 * ds_init_aml_walk. For now, keeps this struct off the CPU stack
	 */
	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	info->parameters = &this_walk_state->operands[0];

	status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node,
				       obj_desc->method.aml_start,
				       obj_desc->method.aml_length, info,
				       ACPI_IMODE_EXECUTE);

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

	/*
	 * Delete the operands on the previous walkstate operand stack
	 * (they were copied to new objects)
	 */
	for (i = 0; i < obj_desc->method.param_count; i++) {
		acpi_ut_remove_reference(this_walk_state->operands[i]);
		this_walk_state->operands[i] = NULL;
	}

	/* Clear the operand stack */

	this_walk_state->num_operands = 0;

	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
			  "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
			  method_node->name.ascii, next_walk_state));

	/* Invoke an internal method if necessary */

	if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
		status = obj_desc->method.implementation(next_walk_state);
		if (status == AE_OK) {
			status = AE_CTRL_TERMINATE;
		}
	}

	return_ACPI_STATUS(status);

      cleanup:

	/* On error, we must terminate the method properly */

	acpi_ds_terminate_control_method(obj_desc, next_walk_state);
	if (next_walk_state) {
		acpi_ds_delete_walk_state(next_walk_state);
	}

	return_ACPI_STATUS(status);
}
Пример #23
0
static ACPI_STATUS
AcpiDbEvaluateOnePredefinedName (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_NAMESPACE_NODE         *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_DB_EXECUTE_WALK        *Info = (ACPI_DB_EXECUTE_WALK *) Context;
    char                        *Pathname;
    const ACPI_PREDEFINED_INFO  *Predefined;
    ACPI_DEVICE_INFO            *ObjInfo;
    ACPI_OBJECT_LIST            ParamObjects;
    ACPI_OBJECT                 Params[ACPI_METHOD_NUM_ARGS];
    ACPI_OBJECT                 *ThisParam;
    ACPI_BUFFER                 ReturnObj;
    ACPI_STATUS                 Status;
    UINT16                      ArgTypeList;
    UINT8                       ArgCount;
    UINT8                       ArgType;
    UINT32                      i;


    /* The name must be a predefined ACPI name */

    Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii);
    if (!Predefined)
    {
        return (AE_OK);
    }

    if (Node->Type == ACPI_TYPE_LOCAL_SCOPE)
    {
        return (AE_OK);
    }

    Pathname = AcpiNsGetNormalizedPathname (Node, TRUE);
    if (!Pathname)
    {
        return (AE_OK);
    }

    /* Get the object info for number of method parameters */

    Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (Pathname);
        return (Status);
    }

    ParamObjects.Count = 0;
    ParamObjects.Pointer = NULL;

    if (ObjInfo->Type == ACPI_TYPE_METHOD)
    {
        /* Setup default parameters (with proper types) */

        ArgTypeList = Predefined->Info.ArgumentList;
        ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList);

        /*
         * Setup the ACPI-required number of arguments, regardless of what
         * the actual method defines. If there is a difference, then the
         * method is wrong and a warning will be issued during execution.
         */
        ThisParam = Params;
        for (i = 0; i < ArgCount; i++)
        {
            ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList);
            ThisParam->Type = ArgType;

            switch (ArgType)
            {
            case ACPI_TYPE_INTEGER:

                ThisParam->Integer.Value = 1;
                break;

            case ACPI_TYPE_STRING:

                ThisParam->String.Pointer =
                    "This is the default argument string";
                ThisParam->String.Length =
                    strlen (ThisParam->String.Pointer);
                break;

            case ACPI_TYPE_BUFFER:

                ThisParam->Buffer.Pointer = (UINT8 *) Params; /* just a garbage buffer */
                ThisParam->Buffer.Length = 48;
                break;

             case ACPI_TYPE_PACKAGE:

                ThisParam->Package.Elements = NULL;
                ThisParam->Package.Count = 0;
                break;

           default:

                AcpiOsPrintf ("%s: Unsupported argument type: %u\n",
                    Pathname, ArgType);
                break;
            }

            ThisParam++;
        }

        ParamObjects.Count = ArgCount;
        ParamObjects.Pointer = Params;
    }

    ACPI_FREE (ObjInfo);
    ReturnObj.Pointer = NULL;
    ReturnObj.Length = ACPI_ALLOCATE_BUFFER;

    /* Do the actual method execution */

    AcpiGbl_MethodExecuting = TRUE;

    Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj);

    AcpiOsPrintf ("%-32s returned %s\n",
        Pathname, AcpiFormatException (Status));
    AcpiGbl_MethodExecuting = FALSE;
    ACPI_FREE (Pathname);

    /* Ignore status from method execution */

    Status = AE_OK;

    /* Update count, check if we have executed enough methods */

    Info->Count++;
    if (Info->Count >= Info->MaxCount)
    {
        Status = AE_CTRL_TERMINATE;
    }

    return (Status);
}
Пример #24
0
ACPI_STATUS
AcpiEvDeleteGpeBlock (
    ACPI_GPE_BLOCK_INFO     *GpeBlock)
{
    ACPI_STATUS             Status;
    ACPI_CPU_FLAGS          Flags;


    ACPI_FUNCTION_TRACE (EvInstallGpeBlock);


    Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
    if (ACPI_FAILURE (Status))
    {
        return_ACPI_STATUS (Status);
    }

    /* Disable all GPEs in this block */

    Status = AcpiHwDisableGpeBlock (GpeBlock->XruptBlock, GpeBlock, NULL);

    if (!GpeBlock->Previous && !GpeBlock->Next)
    {
        /* This is the last GpeBlock on this interrupt */

        Status = AcpiEvDeleteGpeXrupt (GpeBlock->XruptBlock);
        if (ACPI_FAILURE (Status))
        {
            goto UnlockAndExit;
        }
    }
    else
    {
        /* Remove the block on this interrupt with lock */

        Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock);
        if (GpeBlock->Previous)
        {
            GpeBlock->Previous->Next = GpeBlock->Next;
        }
        else
        {
            GpeBlock->XruptBlock->GpeBlockListHead = GpeBlock->Next;
        }

        if (GpeBlock->Next)
        {
            GpeBlock->Next->Previous = GpeBlock->Previous;
        }

        AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags);
    }

    AcpiCurrentGpeCount -= GpeBlock->GpeCount;

    /* Free the GpeBlock */

    ACPI_FREE (GpeBlock->RegisterInfo);
    ACPI_FREE (GpeBlock->EventInfo);
    ACPI_FREE (GpeBlock);

UnlockAndExit:
    Status = AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
    return_ACPI_STATUS (Status);
}
Пример #25
0
ACPI_STATUS
AcpiNsInitializeDevices (
    void)
{
    ACPI_STATUS             Status;
    ACPI_DEVICE_WALK_INFO   Info;


    ACPI_FUNCTION_TRACE (NsInitializeDevices);


    /* Init counters */

    Info.DeviceCount = 0;
    Info.Num_STA = 0;
    Info.Num_INI = 0;

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "Initializing Device/Processor/Thermal objects "
        "and executing _INI/_STA methods:\n"));

    /* Tree analysis: find all subtrees that contain _INI methods */

    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    /* Allocate the evaluation information block */

    Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    if (!Info.EvaluateInfo)
    {
        Status = AE_NO_MEMORY;
        goto ErrorExit;
    }

    /*
     * Execute the "global" _INI method that may appear at the root. This
     * support is provided for Windows compatibility (Vista+) and is not
     * part of the ACPI specification.
     */
    Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
    Info.EvaluateInfo->RelativePathname = __UNCONST(METHOD_NAME__INI);
    Info.EvaluateInfo->Parameters = NULL;
    Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;

    Status = AcpiNsEvaluate (Info.EvaluateInfo);
    if (ACPI_SUCCESS (Status))
    {
        Info.Num_INI++;
    }

    /* Walk namespace to execute all _INIs on present devices */

    Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
                ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);

    /*
     * Any _OSI requests should be completed by now. If the BIOS has
     * requested any Windows OSI strings, we will always truncate
     * I/O addresses to 16 bits -- for Windows compatibility.
     */
    if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
    {
        AcpiGbl_TruncateIoAddresses = TRUE;
    }

    ACPI_FREE (Info.EvaluateInfo);
    if (ACPI_FAILURE (Status))
    {
        goto ErrorExit;
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "    Executed %u _INI methods requiring %u _STA executions "
        "(examined %u objects)\n",
        Info.Num_INI, Info.Num_STA, Info.DeviceCount));

    return_ACPI_STATUS (Status);


ErrorExit:
    ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
    return_ACPI_STATUS (Status);
}
Пример #26
0
static ACPI_STATUS
AcpiEvCreateGpeInfoBlocks (
    ACPI_GPE_BLOCK_INFO     *GpeBlock)
{
    ACPI_GPE_REGISTER_INFO  *GpeRegisterInfo = NULL;
    ACPI_GPE_EVENT_INFO     *GpeEventInfo = NULL;
    ACPI_GPE_EVENT_INFO     *ThisEvent;
    ACPI_GPE_REGISTER_INFO  *ThisRegister;
    UINT32                  i;
    UINT32                  j;
    ACPI_STATUS             Status;


    ACPI_FUNCTION_TRACE (EvCreateGpeInfoBlocks);


    /* Allocate the GPE register information block */

    GpeRegisterInfo = ACPI_ALLOCATE_ZEROED (
        (ACPI_SIZE) GpeBlock->RegisterCount *
        sizeof (ACPI_GPE_REGISTER_INFO));
    if (!GpeRegisterInfo)
    {
        ACPI_ERROR ((AE_INFO,
            "Could not allocate the GpeRegisterInfo table"));
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /*
     * Allocate the GPE EventInfo block. There are eight distinct GPEs
     * per register. Initialization to zeros is sufficient.
     */
    GpeEventInfo = ACPI_ALLOCATE_ZEROED ((ACPI_SIZE) GpeBlock->GpeCount *
        sizeof (ACPI_GPE_EVENT_INFO));
    if (!GpeEventInfo)
    {
        ACPI_ERROR ((AE_INFO,
            "Could not allocate the GpeEventInfo table"));
        Status = AE_NO_MEMORY;
        goto ErrorExit;
    }

    /* Save the new Info arrays in the GPE block */

    GpeBlock->RegisterInfo = GpeRegisterInfo;
    GpeBlock->EventInfo = GpeEventInfo;

    /*
     * Initialize the GPE Register and Event structures. A goal of these
     * tables is to hide the fact that there are two separate GPE register
     * sets in a given GPE hardware block, the status registers occupy the
     * first half, and the enable registers occupy the second half.
     */
    ThisRegister = GpeRegisterInfo;
    ThisEvent = GpeEventInfo;

    for (i = 0; i < GpeBlock->RegisterCount; i++)
    {
        /* Init the RegisterInfo for this GPE register (8 GPEs) */

        ThisRegister->BaseGpeNumber = (UINT16)
            (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH));

        ThisRegister->StatusAddress.Address =
            GpeBlock->Address + i;

        ThisRegister->EnableAddress.Address =
            GpeBlock->Address + i + GpeBlock->RegisterCount;

        ThisRegister->StatusAddress.SpaceId   = GpeBlock->SpaceId;
        ThisRegister->EnableAddress.SpaceId   = GpeBlock->SpaceId;
        ThisRegister->StatusAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
        ThisRegister->EnableAddress.BitWidth  = ACPI_GPE_REGISTER_WIDTH;
        ThisRegister->StatusAddress.BitOffset = 0;
        ThisRegister->EnableAddress.BitOffset = 0;

        /* Init the EventInfo for each GPE within this register */

        for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++)
        {
            ThisEvent->GpeNumber = (UINT8) (ThisRegister->BaseGpeNumber + j);
            ThisEvent->RegisterInfo = ThisRegister;
            ThisEvent++;
        }

        /* Disable all GPEs within this register */

        Status = AcpiHwWrite (0x00, &ThisRegister->EnableAddress);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        /* Clear any pending GPE events within this register */

        Status = AcpiHwWrite (0xFF, &ThisRegister->StatusAddress);
        if (ACPI_FAILURE (Status))
        {
            goto ErrorExit;
        }

        ThisRegister++;
    }

    return_ACPI_STATUS (AE_OK);


ErrorExit:
    if (GpeRegisterInfo)
    {
        ACPI_FREE (GpeRegisterInfo);
    }
    if (GpeEventInfo)
    {
        ACPI_FREE (GpeEventInfo);
    }

    return_ACPI_STATUS (Status);
}
Пример #27
0
static ACPI_STATUS
AcpiDbBusWalk (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    ACPI_STATUS             Status;
    ACPI_BUFFER             Buffer;
    ACPI_NAMESPACE_NODE     *TempNode;
    ACPI_DEVICE_INFO        *Info;
    UINT32                  i;


    if ((Node->Type != ACPI_TYPE_DEVICE) &&
        (Node->Type != ACPI_TYPE_PROCESSOR))
    {
        return (AE_OK);
    }

    /* Exit if there is no _PRT under this device */

    Status = AcpiGetHandle (Node, METHOD_NAME__PRT,
                ACPI_CAST_PTR (ACPI_HANDLE, &TempNode));
    if (ACPI_FAILURE (Status))
    {
        return (AE_OK);
    }

    /* Get the full path to this device object */

    Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
    Status = AcpiNsHandleToPathname (ObjHandle, &Buffer);
    if (ACPI_FAILURE (Status))
    {
        AcpiOsPrintf ("Could Not get pathname for object %p\n", ObjHandle);
        return (AE_OK);
    }

    Status = AcpiGetObjectInfo (ObjHandle, &Info);
    if (ACPI_FAILURE (Status))
    {
        return (AE_OK);
    }

    /* Display the full path */

    AcpiOsPrintf ("%-32s Type %X", (char *) Buffer.Pointer, Node->Type);
    ACPI_FREE (Buffer.Pointer);

    if (Info->Flags & ACPI_PCI_ROOT_BRIDGE)
    {
        AcpiOsPrintf ("  - Is PCI Root Bridge");
    }
    AcpiOsPrintf ("\n");

    /* _PRT info */

    AcpiOsPrintf ("_PRT: %p\n", TempNode);

    /* Dump _ADR, _HID, _UID, _CID */

    if (Info->Valid & ACPI_VALID_ADR)
    {
        AcpiOsPrintf ("_ADR: %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (Info->Address));
    }
    else
    {
        AcpiOsPrintf ("_ADR: <Not Present>\n");
    }

    if (Info->Valid & ACPI_VALID_HID)
    {
        AcpiOsPrintf ("_HID: %s\n", Info->HardwareId.String);
    }
    else
    {
        AcpiOsPrintf ("_HID: <Not Present>\n");
    }

    if (Info->Valid & ACPI_VALID_UID)
    {
        AcpiOsPrintf ("_UID: %s\n", Info->UniqueId.String);
    }
    else
    {
        AcpiOsPrintf ("_UID: <Not Present>\n");
    }

    if (Info->Valid & ACPI_VALID_CID)
    {
        for (i = 0; i < Info->CompatibleIdList.Count; i++)
        {
            AcpiOsPrintf ("_CID: %s\n",
                Info->CompatibleIdList.Ids[i].String);
        }
    }
    else
    {
        AcpiOsPrintf ("_CID: <Not Present>\n");
    }

    ACPI_FREE (Info);
    return (AE_OK);
}
Пример #28
0
ACPI_STATUS
AcpiEvCreateGpeBlock (
    ACPI_NAMESPACE_NODE     *GpeDevice,
    UINT64                  Address,
    UINT8                   SpaceId,
    UINT32                  RegisterCount,
    UINT16                  GpeBlockBaseNumber,
    UINT32                  InterruptNumber,
    ACPI_GPE_BLOCK_INFO     **ReturnGpeBlock)
{
    ACPI_STATUS             Status;
    ACPI_GPE_BLOCK_INFO     *GpeBlock;
    ACPI_GPE_WALK_INFO      WalkInfo;


    ACPI_FUNCTION_TRACE (EvCreateGpeBlock);


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

    /* Allocate a new GPE block */

    GpeBlock = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_BLOCK_INFO));
    if (!GpeBlock)
    {
        return_ACPI_STATUS (AE_NO_MEMORY);
    }

    /* Initialize the new GPE block */

    GpeBlock->Address = Address;
    GpeBlock->SpaceId = SpaceId;
    GpeBlock->Node = GpeDevice;
    GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH);
    GpeBlock->Initialized = FALSE;
    GpeBlock->RegisterCount = RegisterCount;
    GpeBlock->BlockBaseNumber = GpeBlockBaseNumber;

    /*
     * Create the RegisterInfo and EventInfo sub-structures
     * Note: disables and clears all GPEs in the block
     */
    Status = AcpiEvCreateGpeInfoBlocks (GpeBlock);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (GpeBlock);
        return_ACPI_STATUS (Status);
    }

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

    Status = AcpiEvInstallGpeBlock (GpeBlock, InterruptNumber);
    if (ACPI_FAILURE (Status))
    {
        ACPI_FREE (GpeBlock->RegisterInfo);
        ACPI_FREE (GpeBlock->EventInfo);
        ACPI_FREE (GpeBlock);
        return_ACPI_STATUS (Status);
    }

    AcpiGbl_AllGpesInitialized = FALSE;

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

    WalkInfo.GpeBlock = GpeBlock;
    WalkInfo.GpeDevice = GpeDevice;
    WalkInfo.ExecuteByOwnerId = FALSE;

    Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, GpeDevice,
        ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK,
        AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL);

    /* Return the new block */

    if (ReturnGpeBlock)
    {
        (*ReturnGpeBlock) = GpeBlock;
    }

    ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
        "    Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n",
        (UINT32) GpeBlock->BlockBaseNumber,
        (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)),
        GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber,
        InterruptNumber == AcpiGbl_FADT.SciInterrupt ? " (SCI)" : ""));

    /* Update global count of currently available GPEs */

    AcpiCurrentGpeCount += GpeBlock->GpeCount;
    return_ACPI_STATUS (AE_OK);
}
Пример #29
0
static ACPI_STATUS
AcpiDbDeviceResources (
    ACPI_HANDLE             ObjHandle,
    UINT32                  NestingLevel,
    void                    *Context,
    void                    **ReturnValue)
{
    ACPI_NAMESPACE_NODE     *Node;
    ACPI_NAMESPACE_NODE     *PrtNode = NULL;
    ACPI_NAMESPACE_NODE     *CrsNode = NULL;
    ACPI_NAMESPACE_NODE     *PrsNode = NULL;
    ACPI_NAMESPACE_NODE     *AeiNode = NULL;
    char                    *ParentPath;
    ACPI_BUFFER             ReturnBuffer;
    ACPI_STATUS             Status;


    Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    ParentPath = AcpiNsGetExternalPathname (Node);
    if (!ParentPath)
    {
        return (AE_NO_MEMORY);
    }

    /* Get handles to the resource methods for this device */

    (void) AcpiGetHandle (Node, METHOD_NAME__PRT, ACPI_CAST_PTR (ACPI_HANDLE, &PrtNode));
    (void) AcpiGetHandle (Node, METHOD_NAME__CRS, ACPI_CAST_PTR (ACPI_HANDLE, &CrsNode));
    (void) AcpiGetHandle (Node, METHOD_NAME__PRS, ACPI_CAST_PTR (ACPI_HANDLE, &PrsNode));
    (void) AcpiGetHandle (Node, METHOD_NAME__AEI, ACPI_CAST_PTR (ACPI_HANDLE, &AeiNode));
    if (!PrtNode && !CrsNode && !PrsNode && !AeiNode)
    {
        goto Cleanup;   /* Nothing to do */
    }

    AcpiOsPrintf ("\nDevice: %s\n", ParentPath);

    /* Prepare for a return object of arbitrary size */

    ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
    ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;


    /* _PRT */

    if (PrtNode)
    {
        AcpiOsPrintf ("Evaluating _PRT\n");

        Status = AcpiEvaluateObject (PrtNode, NULL, NULL, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not evaluate _PRT: %s\n",
                AcpiFormatException (Status));
            goto GetCrs;
        }

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiGetIrqRoutingTable (Node, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("GetIrqRoutingTable failed: %s\n",
                AcpiFormatException (Status));
            goto GetCrs;
        }

        AcpiRsDumpIrqList (ACPI_CAST_PTR (UINT8, AcpiGbl_DbBuffer));
    }


    /* _CRS */

GetCrs:
    if (CrsNode)
    {
        AcpiOsPrintf ("Evaluating _CRS\n");

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiEvaluateObject (CrsNode, NULL, NULL, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not evaluate _CRS: %s\n",
                AcpiFormatException (Status));
            goto GetPrs;
        }

        /* This code exercises the AcpiWalkResources interface */

        Status = AcpiWalkResources (Node, METHOD_NAME__CRS,
            AcpiDbResourceCallback, NULL);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiWalkResources failed: %s\n",
                AcpiFormatException (Status));
            goto GetPrs;
        }

        /* Get the _CRS resource list (test ALLOCATE buffer) */

        ReturnBuffer.Pointer = NULL;
        ReturnBuffer.Length  = ACPI_ALLOCATE_LOCAL_BUFFER;

        Status = AcpiGetCurrentResources (Node, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiGetCurrentResources failed: %s\n",
                AcpiFormatException (Status));
            goto GetPrs;
        }

        /* This code exercises the AcpiWalkResourceBuffer interface */

        Status = AcpiWalkResourceBuffer (&ReturnBuffer,
            AcpiDbResourceCallback, NULL);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiWalkResourceBuffer failed: %s\n",
                AcpiFormatException (Status));
            goto EndCrs;
        }

        /* Dump the _CRS resource list */

        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE,
            ReturnBuffer.Pointer));

        /*
         * Perform comparison of original AML to newly created AML. This
         * tests both the AML->Resource conversion and the Resource->AML
         * conversion.
         */
        (void) AcpiDmTestResourceConversion (Node, __UNCONST(METHOD_NAME__CRS));

        /* Execute _SRS with the resource list */

        AcpiOsPrintf ("Evaluating _SRS\n");

        Status = AcpiSetCurrentResources (Node, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiSetCurrentResources failed: %s\n",
                AcpiFormatException (Status));
            goto EndCrs;
        }

EndCrs:
        ACPI_FREE_BUFFER (ReturnBuffer);
    }


    /* _PRS */

GetPrs:
    if (PrsNode)
    {
        AcpiOsPrintf ("Evaluating _PRS\n");

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiEvaluateObject (PrsNode, NULL, NULL, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not evaluate _PRS: %s\n",
                AcpiFormatException (Status));
            goto GetAei;
        }

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiGetPossibleResources (Node, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiGetPossibleResources failed: %s\n",
                AcpiFormatException (Status));
            goto GetAei;
        }

        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer));
    }


    /* _AEI */

GetAei:
    if (AeiNode)
    {
        AcpiOsPrintf ("Evaluating _AEI\n");

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiEvaluateObject (AeiNode, NULL, NULL, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("Could not evaluate _AEI: %s\n",
                AcpiFormatException (Status));
            goto Cleanup;
        }

        ReturnBuffer.Pointer = AcpiGbl_DbBuffer;
        ReturnBuffer.Length  = ACPI_DEBUG_BUFFER_SIZE;

        Status = AcpiGetEventResources (Node, &ReturnBuffer);
        if (ACPI_FAILURE (Status))
        {
            AcpiOsPrintf ("AcpiGetEventResources failed: %s\n",
                AcpiFormatException (Status));
            goto Cleanup;
        }

        AcpiRsDumpResourceList (ACPI_CAST_PTR (ACPI_RESOURCE, AcpiGbl_DbBuffer));
    }


Cleanup:
    ACPI_FREE (ParentPath);
    return (AE_OK);
}
Пример #30
0
/*******************************************************************************
 *
 * FUNCTION:    acpi_evaluate_object
 *
 * PARAMETERS:  handle              - Object handle (optional)
 *              pathname            - Object pathname (optional)
 *              external_params     - List of parameters to pass to method,
 *                                    terminated by NULL. May be NULL
 *                                    if no parameters are being passed.
 *              return_buffer       - Where to put method's return value (if
 *                                    any). If NULL, no value is returned.
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Find and evaluate the given object, passing the given
 *              parameters if necessary. One of "Handle" or "Pathname" must
 *              be valid (non-null)
 *
 ******************************************************************************/
acpi_status
acpi_evaluate_object(acpi_handle handle,
		     acpi_string pathname,
		     struct acpi_object_list *external_params,
		     struct acpi_buffer *return_buffer)
{
	acpi_status status;
	struct acpi_evaluate_info *info;
	acpi_size buffer_space_needed;
	u32 i;

	ACPI_FUNCTION_TRACE(acpi_evaluate_object);

	/* Allocate and initialize the evaluation information block */

	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
	if (!info) {
		return_ACPI_STATUS(AE_NO_MEMORY);
	}

	/* Convert and validate the device handle */

	info->prefix_node = acpi_ns_validate_handle(handle);
	if (!info->prefix_node) {
		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	/*
	 * Get the actual namespace node for the target object.
	 * Handles these cases:
	 *
	 * 1) Null node, valid pathname from root (absolute path)
	 * 2) Node and valid pathname (path relative to Node)
	 * 3) Node, Null pathname
	 */
	if ((pathname) && (ACPI_IS_ROOT_PREFIX(pathname[0]))) {

		/* The path is fully qualified, just evaluate by name */

		info->prefix_node = NULL;
	} else if (!handle) {
		/*
		 * A handle is optional iff a fully qualified pathname is specified.
		 * Since we've already handled fully qualified names above, this is
		 * an error.
		 */
		if (!pathname) {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Both Handle and Pathname are NULL"));
		} else {
			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
					  "Null Handle with relative pathname [%s]",
					  pathname));
		}

		status = AE_BAD_PARAMETER;
		goto cleanup;
	}

	info->relative_pathname = pathname;

	/*
	 * Convert all external objects passed as arguments to the
	 * internal version(s).
	 */
	if (external_params && external_params->count) {
		info->param_count = (u16)external_params->count;

		/* Warn on impossible argument count */

		if (info->param_count > ACPI_METHOD_NUM_ARGS) {
			ACPI_WARN_PREDEFINED((AE_INFO, pathname,
					      ACPI_WARN_ALWAYS,
					      "Excess arguments (%u) - using only %u",
					      info->param_count,
					      ACPI_METHOD_NUM_ARGS));

			info->param_count = ACPI_METHOD_NUM_ARGS;
		}

		/*
		 * Allocate a new parameter block for the internal objects
		 * Add 1 to count to allow for null terminated internal list
		 */
		info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) info->
							 param_count +
							 1) * sizeof(void *));
		if (!info->parameters) {
			status = AE_NO_MEMORY;
			goto cleanup;
		}

		/* Convert each external object in the list to an internal object */

		for (i = 0; i < info->param_count; i++) {
			status =
			    acpi_ut_copy_eobject_to_iobject(&external_params->
							    pointer[i],
							    &info->
							    parameters[i]);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
		}

		info->parameters[info->param_count] = NULL;
	}

#if 0

	/*
	 * Begin incoming argument count analysis. Check for too few args
	 * and too many args.
	 */

	switch (acpi_ns_get_type(info->node)) {
	case ACPI_TYPE_METHOD:

		/* Check incoming argument count against the method definition */

		if (info->obj_desc->method.param_count > info->param_count) {
			ACPI_ERROR((AE_INFO,
				    "Insufficient arguments (%u) - %u are required",
				    info->param_count,
				    info->obj_desc->method.param_count));

			status = AE_MISSING_ARGUMENTS;
			goto cleanup;
		}

		else if (info->obj_desc->method.param_count < info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "Excess arguments (%u) - only %u are required",
				      info->param_count,
				      info->obj_desc->method.param_count));

			/* Just pass the required number of arguments */

			info->param_count = info->obj_desc->method.param_count;
		}

		/*
		 * Any incoming external objects to be passed as arguments to the
		 * method must be converted to internal objects
		 */
		if (info->param_count) {
			/*
			 * Allocate a new parameter block for the internal objects
			 * Add 1 to count to allow for null terminated internal list
			 */
			info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size)
								 info->
								 param_count +
								 1) *
								sizeof(void *));
			if (!info->parameters) {
				status = AE_NO_MEMORY;
				goto cleanup;
			}

			/* Convert each external object in the list to an internal object */

			for (i = 0; i < info->param_count; i++) {
				status =
				    acpi_ut_copy_eobject_to_iobject
				    (&external_params->pointer[i],
				     &info->parameters[i]);
				if (ACPI_FAILURE(status)) {
					goto cleanup;
				}
			}

			info->parameters[info->param_count] = NULL;
		}
		break;

	default:

		/* Warn if arguments passed to an object that is not a method */

		if (info->param_count) {
			ACPI_WARNING((AE_INFO,
				      "%u arguments were passed to a non-method ACPI object",
				      info->param_count));
		}
		break;
	}

#endif

	/* Now we can evaluate the object */

	status = acpi_ns_evaluate(info);

	/*
	 * If we are expecting a return value, and all went well above,
	 * copy the return value to an external object.
	 */
	if (return_buffer) {
		if (!info->return_object) {
			return_buffer->length = 0;
		} else {
			if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) ==
			    ACPI_DESC_TYPE_NAMED) {
				/*
				 * If we received a NS Node as a return object, this means that
				 * the object we are evaluating has nothing interesting to
				 * return (such as a mutex, etc.)  We return an error because
				 * these types are essentially unsupported by this interface.
				 * We don't check up front because this makes it easier to add
				 * support for various types at a later date if necessary.
				 */
				status = AE_TYPE;
				info->return_object = NULL;	/* No need to delete a NS Node */
				return_buffer->length = 0;
			}

			if (ACPI_SUCCESS(status)) {

				/* Dereference Index and ref_of references */

				acpi_ns_resolve_references(info);

				/* Get the size of the returned object */

				status =
				    acpi_ut_get_object_size(info->return_object,
							    &buffer_space_needed);
				if (ACPI_SUCCESS(status)) {

					/* Validate/Allocate/Clear caller buffer */

					status =
					    acpi_ut_initialize_buffer
					    (return_buffer,
					     buffer_space_needed);
					if (ACPI_FAILURE(status)) {
						/*
						 * Caller's buffer is too small or a new one can't
						 * be allocated
						 */
						ACPI_DEBUG_PRINT((ACPI_DB_INFO,
								  "Needed buffer size %X, %s\n",
								  (u32)
								  buffer_space_needed,
								  acpi_format_exception
								  (status)));
					} else {
						/* We have enough space for the object, build it */

						status =
						    acpi_ut_copy_iobject_to_eobject
						    (info->return_object,
						     return_buffer);
					}
				}
			}
		}
	}

	if (info->return_object) {
		/*
		 * Delete the internal return object. NOTE: Interpreter must be
		 * locked to avoid race condition.
		 */
		acpi_ex_enter_interpreter();

		/* Remove one reference on the return object (should delete it) */

		acpi_ut_remove_reference(info->return_object);
		acpi_ex_exit_interpreter();
	}

cleanup:

	/* Free the input parameter list (if we created one) */

	if (info->parameters) {

		/* Free the allocated parameter block */

		acpi_ut_delete_internal_object_list(info->parameters);
	}

	ACPI_FREE(info);
	return_ACPI_STATUS(status);
}