void AcpiNsTerminate ( void) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_TRACE (NsTerminate); /* * 1) Free the entire namespace -- all nodes and objects * * Delete all object descriptors attached to namepsace nodes */ AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); /* Detach any objects attached to the root */ ObjDesc = AcpiNsGetAttachedObject (AcpiGbl_RootNode); if (ObjDesc) { AcpiNsDetachObject (AcpiGbl_RootNode); } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; }
void AcpiNsTerminate ( void) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsTerminate); /* * Free the entire namespace -- all nodes and all objects * attached to the nodes */ AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); /* Delete any objects attached to the root node */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } AcpiNsDeleteNode (AcpiGbl_RootNode); (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; }
void AcpiNsTerminate ( void) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsTerminate); #ifdef ACPI_EXEC_APP { ACPI_OPERAND_OBJECT *Prev; ACPI_OPERAND_OBJECT *Next; /* Delete any module-level code blocks */ Next = AcpiGbl_ModuleCodeList; while (Next) { Prev = Next; Next = Next->Method.Mutex; Prev->Method.Mutex = NULL; /* Clear the Mutex (cheated) field */ AcpiUtRemoveReference (Prev); } } #endif /* * Free the entire namespace -- all nodes and all objects * attached to the nodes */ AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); /* Delete any objects attached to the root node */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_VOID; } AcpiNsDeleteNode (AcpiGbl_RootNode); (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Namespace freed\n")); return_VOID; }
ACPI_STATUS AcpiDbDisassembleMethod ( char *Name) { ACPI_STATUS Status; ACPI_PARSE_OBJECT *Op; ACPI_WALK_STATE *WalkState; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Method; Method = AcpiDbConvertToNode (Name); if (!Method) { return (AE_BAD_PARAMETER); } if (Method->Type != ACPI_TYPE_METHOD) { ACPI_ERROR ((AE_INFO, "%s (%s): Object must be a control method", Name, AcpiUtGetTypeName (Method->Type))); return (AE_BAD_PARAMETER); } ObjDesc = Method->Object; Op = AcpiPsCreateScopeOp (); if (!Op) { return (AE_NO_MEMORY); } /* Create and initialize a new walk state */ WalkState = AcpiDsCreateWalkState (0, Op, NULL, NULL); if (!WalkState) { return (AE_NO_MEMORY); } Status = AcpiDsInitAmlWalk (WalkState, Op, NULL, ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, ACPI_IMODE_LOAD_PASS1); if (ACPI_FAILURE (Status)) { return (Status); } Status = AcpiUtAllocateOwnerId (&ObjDesc->Method.OwnerId); WalkState->OwnerId = ObjDesc->Method.OwnerId; /* Push start scope on scope stack and make it current */ Status = AcpiDsScopeStackPush (Method, Method->Type, WalkState); if (ACPI_FAILURE (Status)) { return (Status); } /* Parse the entire method AML including deferred operators */ WalkState->ParseFlags &= ~ACPI_PARSE_DELETE_TREE; WalkState->ParseFlags |= ACPI_PARSE_DISASSEMBLE; Status = AcpiPsParseAml (WalkState); (void) AcpiDmParseDeferredOps (Op); /* Now we can disassemble the method */ AcpiGbl_DbOpt_verbose = FALSE; AcpiDmDisassemble (NULL, Op, 0); AcpiGbl_DbOpt_verbose = TRUE; AcpiPsDeleteParseTree (Op); /* Method cleanup */ AcpiNsDeleteNamespaceSubtree (Method); AcpiNsDeleteNamespaceByOwner (ObjDesc->Method.OwnerId); AcpiUtReleaseOwnerId (&ObjDesc->Method.OwnerId); return (AE_OK); }
void AcpiDsTerminateControlMethod ( ACPI_OPERAND_OBJECT *MethodDesc, ACPI_WALK_STATE *WalkState) { ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); /* MethodDesc is required, WalkState is optional */ if (!MethodDesc) { return_VOID; } if (WalkState) { /* Delete all arguments and locals */ AcpiDsMethodDataDeleteAll (WalkState); /* * If method is serialized, release the mutex and restore the * current sync level for this thread */ if (MethodDesc->Method.Mutex) { /* Acquisition Depth handles recursive calls */ MethodDesc->Method.Mutex->Mutex.AcquisitionDepth--; if (!MethodDesc->Method.Mutex->Mutex.AcquisitionDepth) { WalkState->Thread->CurrentSyncLevel = MethodDesc->Method.Mutex->Mutex.OriginalSyncLevel; AcpiOsReleaseMutex (MethodDesc->Method.Mutex->Mutex.OsMutex); MethodDesc->Method.Mutex->Mutex.ThreadId = 0; } } /* * Delete any namespace objects created anywhere within the * namespace by the execution of this method. Unless: * 1) This method is a module-level executable code method, in which * case we want make the objects permanent. * 2) There are other threads executing the method, in which case we * will wait until the last thread has completed. */ if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) && (MethodDesc->Method.ThreadCount == 1)) { /* Delete any direct children of (created by) this method */ AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode); /* * Delete any objects that were created by this method * elsewhere in the namespace (if any were created). * Use of the ACPI_METHOD_MODIFIED_NAMESPACE optimizes the * deletion such that we don't have to perform an entire * namespace walk for every control method execution. */ if (MethodDesc->Method.InfoFlags & ACPI_METHOD_MODIFIED_NAMESPACE) { AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_MODIFIED_NAMESPACE; } } } /* Decrement the thread count on the method */ if (MethodDesc->Method.ThreadCount) { MethodDesc->Method.ThreadCount--; } else { ACPI_ERROR ((AE_INFO, "Invalid zero thread count in method")); } /* Are there any other threads currently executing this method? */ if (MethodDesc->Method.ThreadCount) { /* * Additional threads. Do not release the OwnerId in this case, * we immediately reuse it for the next thread executing this method */ ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "*** Completed execution of one thread, %u threads remaining\n", MethodDesc->Method.ThreadCount)); } else { /* This is the only executing thread for this method */ /* * Support to dynamically change a method from NotSerialized to * Serialized if it appears that the method is incorrectly written and * does not support multiple thread execution. The best example of this * is if such a method creates namespace objects and blocks. A second * thread will fail with an AE_ALREADY_EXISTS exception. * * This code is here because we must wait until the last thread exits * before marking the method as serialized. */ if (MethodDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED_PENDING) { if (WalkState) { ACPI_INFO ((AE_INFO, "Marking method %4.4s as Serialized because of AE_ALREADY_EXISTS error", WalkState->MethodNode->Name.Ascii)); } /* * Method tried to create an object twice and was marked as * "pending serialized". The probable cause is that the method * cannot handle reentrancy. * * The method was created as NotSerialized, but it tried to create * a named object and then blocked, causing the second thread * entrance to begin and then fail. Workaround this problem by * marking the method permanently as Serialized when the last * thread exits here. */ MethodDesc->Method.InfoFlags &= ~ACPI_METHOD_SERIALIZED_PENDING; MethodDesc->Method.InfoFlags |= ACPI_METHOD_SERIALIZED; MethodDesc->Method.SyncLevel = 0; } /* No more threads, we can free the OwnerId */ if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)) { AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); } } return_VOID; }
ACPI_STATUS AdAmlDisassemble ( BOOLEAN OutToFile, char *Filename, char *Prefix, char **OutFilename, BOOLEAN GetAllTables) { ACPI_STATUS Status; char *DisasmFilename = NULL; char *ExternalFilename; ACPI_EXTERNAL_FILE *ExternalFileList = AcpiGbl_ExternalFileList; 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 */ while (ExternalFileList) { ExternalFilename = ExternalFileList->Path; if (!ACPI_STRCMP (ExternalFilename, Filename)) { /* Next external file */ ExternalFileList = ExternalFileList->Next; continue; } 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 */ ExternalFileList = ExternalFileList->Next; } /* Clear external list generated by Scope in external tables */ if (AcpiGbl_ExternalFileList) { 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\n", Table->Signature); fprintf (stderr, "Formatted output: %s - %u bytes\n", DisasmFilename, AdGetFileSize (File)); } 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"); NsSetupNamespaceListing (File); NsDisplayNamespace (); 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); /* * 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 %u 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.Parent = NULL; AcpiGbl_RootNodeStruct.Child = NULL; AcpiGbl_RootNodeStruct.Peer = NULL; AcpiGbl_RootNodeStruct.Object = NULL; AcpiGbl_RootNodeStruct.Flags = 0; Status = AcpiNsRootInitialize (); AcpiDmAddExternalsToNamespace (); /* Parse the table again. No need to reload it, however */ 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"); NsSetupNamespaceListing (File); NsDisplayNamespace (); AcpiOsPrintf ("*****/\n"); AcpiDmDumpTree (AcpiGbl_ParseOpRoot); } } /* * Now that the namespace is finalized, we can perform namespace * transforms. * * 1) Convert fixed-offset references to resource descriptors * to symbolic references (Note: modifies namespace) */ AcpiDmConvertResourceIndexes (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode); /* Optional displays */ if (AcpiGbl_DbOpt_disasm) { /* This is the real disassembly */ AdDisplayTables (Filename, Table); /* Dump hex table if requested (-vt) */ AcpiDmDumpDataTable (Table); fprintf (stderr, "Disassembly completed\n"); fprintf (stderr, "ASL Output: %s - %u bytes\n", DisasmFilename, AdGetFileSize (File)); } } Cleanup: if (Table && !AcpiUtIsAmlTable (Table)) { ACPI_FREE (Table); } if (OutToFile && File) { if (AslCompilerdebug) /* Display final namespace, with transforms */ { NsSetupNamespaceListing (File); NsDisplayNamespace (); } fclose (File); AcpiOsRedirectOutput (stdout); } AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); AcpiGbl_ParseOpRoot = NULL; return (Status); }
ACPI_STATUS AcpiDsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OBJECT_TYPE Type; ACPI_STATUS Status; ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_FUNCTION_NAME ("DsInitOneObject"); /* * We are only interested in objects owned by the table that * was just loaded */ if (((ACPI_NAMESPACE_NODE *) ObjHandle)->OwnerId != Info->TableDesc->TableId) { return (AE_OK); } Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); switch (Type) { case ACPI_TYPE_REGION: Status = AcpiDsInitializeRegion (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Region %p [%4.4s] - Init failure, %s\n", ObjHandle, ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii, AcpiFormatException (Status))); } Info->OpRegionCount++; break; case ACPI_TYPE_METHOD: Info->MethodCount++; /* Print a dot for each method unless we are going to print the entire pathname */ if (!(AcpiDbgLevel & ACPI_LV_INIT_NAMES)) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, ".")); } /* * Set the execution data width (32 or 64) based upon the * revision number of the parent ACPI table. * TBD: This is really for possible future support of integer width * on a per-table basis. Currently, we just use a global for the width. */ if (Info->TableDesc->Pointer->Revision == 1) { ((ACPI_NAMESPACE_NODE *) ObjHandle)->Flags |= ANOBJ_DATA_WIDTH_32; } /* * Always parse methods to detect errors, we may delete * the parse tree below */ Status = AcpiDsParseMethod (ObjHandle); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Method %p [%4.4s] - parse failure, %s\n", ObjHandle, ((ACPI_NAMESPACE_NODE *) ObjHandle)->Name.Ascii, AcpiFormatException (Status))); /* This parse failed, but we will continue parsing more methods */ break; } /* * Delete the parse tree. We simple re-parse the method * for every execution since there isn't much overhead */ AcpiNsDeleteNamespaceSubtree (ObjHandle); AcpiNsDeleteNamespaceByOwner (((ACPI_NAMESPACE_NODE *) ObjHandle)->Object->Method.OwningId); break; case ACPI_TYPE_DEVICE: Info->DeviceCount++; break; default: break; } /* * We ignore errors from above, and always return OK, since * we don't want to abort the walk on a single error. */ return (AE_OK); }
static ACPI_STATUS AdReparseOneTable ( ACPI_TABLE_HEADER *Table, FILE *File, ACPI_OWNER_ID OwnerId) { ACPI_STATUS Status; fprintf (stderr, "\nFound %u external control methods, " "reparsing with new information\n", AcpiDmGetExternalMethodCount ()); /* Reparse, rebuild namespace */ AcpiPsDeleteParseTree (AcpiGbl_ParseOpRoot); AcpiGbl_ParseOpRoot = NULL; 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.Parent = NULL; AcpiGbl_RootNodeStruct.Child = NULL; AcpiGbl_RootNodeStruct.Peer = NULL; AcpiGbl_RootNodeStruct.Object = NULL; AcpiGbl_RootNodeStruct.Flags = 0; Status = AcpiNsRootInitialize (); if (ACPI_FAILURE (Status)) { return (Status); } /* New namespace, add the external definitions first */ AcpiDmAddExternalsToNamespace (); /* Parse the table again. No need to reload it, however */ Status = AdParseTable (Table, NULL, FALSE, FALSE); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Could not parse ACPI tables, %s\n", AcpiFormatException (Status)); return (Status); } /* Cross reference the namespace again */ AcpiDmFinishNamespaceLoad (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId); AcpiDmCrossReferenceNamespace (AcpiGbl_ParseOpRoot, AcpiGbl_RootNode, OwnerId); /* Debug output - namespace and parse tree */ if (AslCompilerdebug) { AcpiOsPrintf ("/**** After second load and resource conversion\n"); if (File) { NsSetupNamespaceListing (File); NsDisplayNamespace (); } AcpiOsPrintf ("*****/\n"); AcpiDmDumpTree (AcpiGbl_ParseOpRoot); } return (AE_OK); }