ACPI_STATUS AcpiTbInstallStandardTable ( ACPI_PHYSICAL_ADDRESS Address, UINT8 Flags, BOOLEAN Reload, BOOLEAN Override, UINT32 *TableIndex) { UINT32 i; ACPI_STATUS Status = AE_OK; ACPI_TABLE_DESC NewTableDesc; ACPI_FUNCTION_TRACE (TbInstallStandardTable); /* Acquire a temporary table descriptor for validation */ Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not acquire table length at %8.8X%8.8X", ACPI_FORMAT_UINT64 (Address))); return_ACPI_STATUS (Status); } /* * Optionally do not load any SSDTs from the RSDT/XSDT. This can * be useful for debugging ACPI problems on some machines. */ if (!Reload && AcpiGbl_DisableSsdtTableInstall && ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) { ACPI_INFO (( "Ignoring installation of %4.4s at %8.8X%8.8X", NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); goto ReleaseAndExit; } /* Acquire the table lock */ (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* Validate and verify a table before installation */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i); if (ACPI_FAILURE (Status)) { if (Status == AE_CTRL_TERMINATE) { /* * Table was unloaded, allow it to be reloaded. * As we are going to return AE_OK to the caller, we should * take the responsibility of freeing the input descriptor. * Refill the input descriptor to ensure * AcpiTbInstallTableWithOverride() can be called again to * indicate the re-installation. */ AcpiTbUninstallTable (&NewTableDesc); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); *TableIndex = i; return_ACPI_STATUS (AE_OK); } goto UnlockAndExit; } /* Add the table to the global root table list */ AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); /* Invoke table handler */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); UnlockAndExit: /* Release the table lock */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); ReleaseAndExit: /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); return_ACPI_STATUS (Status); }
void AcpiUtDumpAllocations ( UINT32 Component, char *Module) { ACPI_DEBUG_MEM_BLOCK *Element; ACPI_DESCRIPTOR *Descriptor; UINT32 NumOutstanding = 0; ACPI_FUNCTION_TRACE (UtDumpAllocations); /* * Walk the allocation list. */ if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) { return; } Element = AcpiGbl_GlobalList->ListHead; while (Element) { if ((Element->Component & Component) && ((Module == NULL) || (0 == ACPI_STRCMP (Module, Element->Module)))) { /* Ignore allocated objects that are in a cache */ Descriptor = ACPI_CAST_PTR (ACPI_DESCRIPTOR, &Element->UserSpace); if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) { AcpiOsPrintf ("%p Len %04X %9.9s-%d [%s] ", Descriptor, Element->Size, Element->Module, Element->Line, AcpiUtGetDescriptorName (Descriptor)); /* Most of the elements will be Operand objects. */ switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) { case ACPI_DESC_TYPE_OPERAND: AcpiOsPrintf ("%12.12s R%hd", AcpiUtGetTypeName (Descriptor->Object.Common.Type), Descriptor->Object.Common.ReferenceCount); break; case ACPI_DESC_TYPE_PARSER: AcpiOsPrintf ("AmlOpcode %04hX", Descriptor->Op.Asl.AmlOpcode); break; case ACPI_DESC_TYPE_NAMED: AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (&Descriptor->Node)); break; default: break; } AcpiOsPrintf ( "\n"); NumOutstanding++; } } Element = Element->Next; } (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); /* Print summary */ if (!NumOutstanding) { ACPI_INFO ((AE_INFO, "No outstanding allocations")); } else { ACPI_ERROR ((AE_INFO, "%d(%X) Outstanding allocations", NumOutstanding, NumOutstanding)); } return_VOID; }
ACPI_STATUS AcpiLoadTable ( ACPI_TABLE_HEADER *Table) { ACPI_STATUS Status; UINT32 TableIndex; ACPI_FUNCTION_TRACE (AcpiLoadTable); /* Parameter validation */ if (!Table) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* Must acquire the interpreter lock during this operation */ Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Install the table and load it into the namespace */ ACPI_INFO ((AE_INFO, "Host-directed Dynamic ACPI Table Load:")); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, TRUE, FALSE, &TableIndex); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* * Note: Now table is "INSTALLED", it must be validated before * using. */ Status = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[TableIndex]); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } Status = AcpiNsLoadTable (TableIndex, AcpiGbl_RootNode); /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, AcpiGbl_TableHandlerContext); } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiNsRootInitialize ( void) { ACPI_STATUS Status; const ACPI_PREDEFINED_NAMES *InitVal = NULL; ACPI_NAMESPACE_NODE *NewNode; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_STRING Val = NULL; ACPI_FUNCTION_TRACE (NsRootInitialize); Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * The global root ptr is initially NULL, so a non-NULL value indicates * that AcpiNsRootInitialize() has already been called; just return. */ if (AcpiGbl_RootNode) { Status = AE_OK; goto UnlockAndExit; } /* * Tell the rest of the subsystem that the root is initialized * (This is OK because the namespace is locked) */ AcpiGbl_RootNode = &AcpiGbl_RootNodeStruct; /* Enter the pre-defined names in the name table */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Entering predefined entries into namespace\n")); for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) { /* _OSI is optional for now, will be permanent later */ if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) { continue; } Status = AcpiNsLookup (NULL, __UNCONST(InitVal->Name), InitVal->Type, ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &NewNode); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create predefined name %s", InitVal->Name)); continue; } /* * Name entered successfully. If entry in PreDefinedNames[] specifies * an initial value, create the initial value. */ if (InitVal->Val) { Status = AcpiOsPredefinedOverride (InitVal, &Val); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Could not override predefined %s", InitVal->Name)); } if (!Val) { Val = __UNCONST(InitVal->Val); } /* * Entry requests an initial value, allocate a * descriptor for it. */ ObjDesc = AcpiUtCreateInternalObject (InitVal->Type); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } /* * Convert value string from table entry to * internal representation. Only types actually * used for initial values are implemented here. */ switch (InitVal->Type) { case ACPI_TYPE_METHOD: ObjDesc->Method.ParamCount = (UINT8) ACPI_TO_INTEGER (Val); ObjDesc->Common.Flags |= AOPOBJ_DATA_VALID; #if defined (ACPI_ASL_COMPILER) /* Save the parameter count for the iASL compiler */ NewNode->Value = ObjDesc->Method.ParamCount; #else /* Mark this as a very SPECIAL method */ ObjDesc->Method.InfoFlags = ACPI_METHOD_INTERNAL_ONLY; ObjDesc->Method.Dispatch.Implementation = AcpiUtOsiImplementation; #endif break; case ACPI_TYPE_INTEGER: ObjDesc->Integer.Value = ACPI_TO_INTEGER (Val); break; case ACPI_TYPE_STRING: /* Build an object around the static string */ ObjDesc->String.Length = (UINT32) strlen (Val); ObjDesc->String.Pointer = Val; ObjDesc->Common.Flags |= AOPOBJ_STATIC_POINTER; break; case ACPI_TYPE_MUTEX: ObjDesc->Mutex.Node = NewNode; ObjDesc->Mutex.SyncLevel = (UINT8) (ACPI_TO_INTEGER (Val) - 1); /* Create a mutex */ Status = AcpiOsCreateMutex (&ObjDesc->Mutex.OsMutex); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); goto UnlockAndExit; } /* Special case for ACPI Global Lock */ if (strcmp (InitVal->Name, "_GL_") == 0) { AcpiGbl_GlobalLockMutex = ObjDesc; /* Create additional counting semaphore for global lock */ Status = AcpiOsCreateSemaphore ( 1, 0, &AcpiGbl_GlobalLockSemaphore); if (ACPI_FAILURE (Status)) { AcpiUtRemoveReference (ObjDesc); goto UnlockAndExit; } } break; default: ACPI_ERROR ((AE_INFO, "Unsupported initial type value 0x%X", InitVal->Type)); AcpiUtRemoveReference (ObjDesc); ObjDesc = NULL; continue; } /* Store pointer to value descriptor in the Node */ Status = AcpiNsAttachObject (NewNode, ObjDesc, ObjDesc->Common.Type); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); } } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); /* Save a handle to "_GPE", it is always present */ if (ACPI_SUCCESS (Status)) { Status = AcpiNsGetNode (NULL, "\\_GPE", ACPI_NS_NO_UPSEARCH, &AcpiGbl_FadtGpeDevice); } return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj, BOOLEAN AcpiNsLocked) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); if (!RegionObj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) { return_ACPI_STATUS (AE_OK); } RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; Node = RegionObj->Region.Node->Parent; SpaceId = RegionObj->Region.SpaceId; /* * The following loop depends upon the root Node having no parent * ie: AcpiGbl_RootNode->Parent being set to NULL */ while (Node) { /* Check to see if a handler exists */ HandlerObj = NULL; ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Can only be a handler if the object exists */ switch (Node->Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: HandlerObj = ObjDesc->CommonNotify.Handler; break; case ACPI_TYPE_METHOD: /* * If we are executing module level code, the original * Node's object was replaced by this Method object and we * saved the handler in the method object. * * See AcpiNsExecModuleCode */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) { HandlerObj = ObjDesc->Method.Dispatch.Handler; } break; default: /* Ignore other objects */ break; } HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); if (HandlerObj) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler %p for region %p in obj %p\n", HandlerObj, RegionObj, ObjDesc)); Status = AcpiEvAttachRegion (HandlerObj, RegionObj, AcpiNsLocked); /* * Tell all users that this region is usable by * running the _REG method */ if (AcpiNsLocked) { Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); if (AcpiNsLocked) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } return_ACPI_STATUS (AE_OK); } } /* This node does not have the handler we need; Pop up one level */ Node = Node->Parent; } /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for RegionType %s(%X) (RegionObj %p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); }
static ACPI_STATUS AcpiDbStartCommand ( ACPI_WALK_STATE *WalkState, ACPI_PARSE_OBJECT *Op) { ACPI_STATUS Status; /* TBD: [Investigate] are there namespace locking issues here? */ /* AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); */ /* Go into the command loop and await next user command */ AcpiGbl_MethodExecuting = TRUE; Status = AE_CTRL_TRUE; while (Status == AE_CTRL_TRUE) { if (AcpiGbl_DebuggerConfiguration == DEBUGGER_MULTI_THREADED) { /* Handshake with the front-end that gets user command lines */ Status = AcpiUtReleaseMutex (ACPI_MTX_DEBUG_CMD_COMPLETE); if (ACPI_FAILURE (Status)) { return (Status); } Status = AcpiUtAcquireMutex (ACPI_MTX_DEBUG_CMD_READY); if (ACPI_FAILURE (Status)) { return (Status); } } else { /* Single threaded, we must get a command line ourselves */ /* Force output to console until a command is entered */ AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); /* Different prompt if method is executing */ if (!AcpiGbl_MethodExecuting) { AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_COMMAND_PROMPT); } else { AcpiOsPrintf ("%1c ", ACPI_DEBUGGER_EXECUTE_PROMPT); } /* Get the user input line */ Status = AcpiOsGetLine (AcpiGbl_DbLineBuf, ACPI_DB_LINE_BUFFER_SIZE, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While parsing command line")); return (Status); } } Status = AcpiDbCommandDispatch (AcpiGbl_DbLineBuf, WalkState, Op); } /* AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); */ return (Status); }
ACPI_STATUS AcpiWalkNamespace ( ACPI_OBJECT_TYPE Type, ACPI_HANDLE StartObject, UINT32 MaxDepth, ACPI_WALK_CALLBACK UserFunction, void *Context, void **ReturnValue) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (AcpiWalkNamespace); /* Parameter validation */ if ((Type > ACPI_TYPE_LOCAL_MAX) || (!MaxDepth) || (!UserFunction)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * Need to acquire the namespace reader lock to prevent interference * with any concurrent table unloads (which causes the deletion of * namespace objects). We cannot allow the deletion of a namespace node * while the user function is using it. The exception to this are the * nodes created and deleted during control method execution -- these * nodes are marked as temporary nodes and are ignored by the namespace * walk. Thus, control methods can be executed while holding the * namespace deletion lock (and the user function can execute control * methods.) */ Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock); if (ACPI_FAILURE (Status)) { return (Status); } /* * Lock the namespace around the walk. The namespace will be * unlocked/locked around each call to the user function - since the user * function must be allowed to make ACPICA calls itself (for example, it * will typically execute control methods during device enumeration.) */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth, ACPI_NS_WALK_UNLOCK, UserFunction, Context, ReturnValue); (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); UnlockAndExit: (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiGetHandle ( ACPI_HANDLE Parent, ACPI_STRING Pathname, ACPI_HANDLE *RetHandle) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node = NULL; ACPI_NAMESPACE_NODE *PrefixNode = NULL; ACPI_FUNCTION_ENTRY (); /* Parameter Validation */ if (!RetHandle || !Pathname) { return (AE_BAD_PARAMETER); } /* Convert a parent handle to a prefix node */ if (Parent) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } PrefixNode = AcpiNsMapHandleToNode (Parent); if (!PrefixNode) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return (AE_BAD_PARAMETER); } Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } } /* Special case for root, since we can't search for it */ if (ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH) == 0) { *RetHandle = AcpiNsConvertEntryToHandle (AcpiGbl_RootNode); return (AE_OK); } /* * Find the Node and convert to a handle */ Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node); *RetHandle = NULL; if (ACPI_SUCCESS (Status)) { *RetHandle = AcpiNsConvertEntryToHandle (Node); } return (Status); }
ACPI_STATUS AcpiGetName ( ACPI_HANDLE Handle, UINT32 NameType, ACPI_BUFFER *Buffer) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; /* Parameter validation */ if (NameType > ACPI_NAME_TYPE_MAX) { return (AE_BAD_PARAMETER); } Status = AcpiUtValidateBuffer (Buffer); if (ACPI_FAILURE (Status)) { return (Status); } if (NameType == ACPI_FULL_PATHNAME) { /* Get the full pathname (From the namespace root) */ Status = AcpiNsHandleToPathname (Handle, Buffer); return (Status); } /* * Wants the single segment ACPI name. * Validate handle and convert to a namespace Node */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } Node = AcpiNsMapHandleToNode (Handle); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Validate/Allocate/Clear caller buffer */ Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Just copy the ACPI name from the Node and zero terminate it */ ACPI_STRNCPY (Buffer->Pointer, AcpiUtGetNodeName (Node), ACPI_NAME_SIZE); ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0; Status = AE_OK; UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return (Status); }
ACPI_STATUS AcpiInstallGpeBlock ( ACPI_HANDLE GpeDevice, ACPI_GENERIC_ADDRESS *GpeBlockAddress, UINT32 RegisterCount, UINT32 InterruptNumber) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_FUNCTION_TRACE (AcpiInstallGpeBlock); if ((!GpeDevice) || (!GpeBlockAddress) || (!RegisterCount)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Node = AcpiNsValidateHandle (GpeDevice); if (!Node) { Status = AE_BAD_PARAMETER; goto UnlockAndExit; } /* Validate the parent device */ if (Node->Type != ACPI_TYPE_DEVICE) { Status = AE_TYPE; goto UnlockAndExit; } if (Node->Object) { Status = AE_ALREADY_EXISTS; goto UnlockAndExit; } /* * For user-installed GPE Block Devices, the GpeBlockBaseNumber * is always zero */ Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, GpeBlockAddress->SpaceId, RegisterCount, 0, InterruptNumber, &GpeBlock); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Install block in the DeviceObject attached to the node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* * No object, create a new one (Device nodes do not always have * an attached object) */ ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_DEVICE); if (!ObjDesc) { Status = AE_NO_MEMORY; goto UnlockAndExit; } Status = AcpiNsAttachObject (Node, ObjDesc, ACPI_TYPE_DEVICE); /* Remove local reference to the object */ AcpiUtRemoveReference (ObjDesc); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } } /* Now install the GPE block in the DeviceObject */ ObjDesc->Device.GpeBlock = GpeBlock; UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (Status); }
void AcpiEvUpdateGpes ( ACPI_OWNER_ID TableOwnerId) { ACPI_GPE_XRUPT_INFO *GpeXruptInfo; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_WALK_INFO WalkInfo; ACPI_STATUS Status = AE_OK; UINT32 NewWakeGpeCount = 0; /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ WalkInfo.OwnerId = TableOwnerId; WalkInfo.ExecuteByOwnerId = TRUE; WalkInfo.Count = 0; if (AcpiGbl_LeaveWakeGpesDisabled) { /* * 1) Run any newly-loaded _PRW methods to find any GPEs that * can now be marked as CAN_WAKE GPEs. Note: We must run the * _PRW methods before we process the _Lxx/_Exx methods because * we will enable all runtime GPEs associated with the new * _Lxx/_Exx methods at the time we process those methods. * * Unlock interpreter so that we can run the _PRW methods. */ WalkInfo.GpeBlock = NULL; WalkInfo.GpeDevice = NULL; AcpiExExitInterpreter (); Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchPrwAndGpe, NULL, &WalkInfo, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While executing _PRW methods")); } AcpiExEnterInterpreter (); NewWakeGpeCount = WalkInfo.Count; } /* * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. * * Any GPEs that correspond to new _Lxx/_Exx methods and are not * marked as CAN_WAKE are immediately enabled. * * Examine the namespace underneath each GpeDevice within the * GpeBlock lists. */ Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return; } WalkInfo.Count = 0; WalkInfo.EnableThisGpe = TRUE; /* Walk the interrupt level descriptor list */ GpeXruptInfo = AcpiGbl_GpeXruptListHead; while (GpeXruptInfo) { /* Walk all Gpe Blocks attached to this interrupt level */ GpeBlock = GpeXruptInfo->GpeBlockListHead; while (GpeBlock) { WalkInfo.GpeBlock = GpeBlock; WalkInfo.GpeDevice = GpeBlock->Node; Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, WalkInfo.GpeDevice, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While decoding _Lxx/_Exx methods")); } GpeBlock = GpeBlock->Next; } GpeXruptInfo = GpeXruptInfo->Next; } if (WalkInfo.Count || NewWakeGpeCount) { ACPI_INFO ((AE_INFO, "Enabled %u new runtime GPEs, added %u new wakeup GPEs", WalkInfo.Count, NewWakeGpeCount)); } (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return; }
ACPI_STATUS AcpiNsLoadTable ( UINT32 TableIndex, ACPI_NAMESPACE_NODE *Node) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsLoadTable); /* * Parse the table and load the namespace with all named * objects found within. Control methods are NOT parsed * at this time. In fact, the control methods cannot be * parsed until the entire namespace is loaded, because * if a control method makes a forward reference (call) * to another control method, we can't continue parsing * because we don't know how many arguments to parse next! */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* If table already loaded into namespace, just return */ if (AcpiTbIsTableLoaded (TableIndex)) { Status = AE_ALREADY_EXISTS; goto Unlock; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Loading table into namespace ****\n")); Status = AcpiTbAllocateOwnerId (TableIndex); if (ACPI_FAILURE (Status)) { goto Unlock; } Status = AcpiNsParseTable (TableIndex, Node); if (ACPI_SUCCESS (Status)) { AcpiTbSetTableLoadedFlag (TableIndex, TRUE); } else { /* * On error, delete any namespace objects created by this table. * We cannot initialize these objects, so delete them. There are * a couple of expecially bad cases: * AE_ALREADY_EXISTS - namespace collision. * AE_NOT_FOUND - the target of a Scope operator does not * exist. This target of Scope must already exist in the * namespace, as per the ACPI specification. */ (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); AcpiNsDeleteNamespaceByOwner ( AcpiGbl_RootTableList.Tables[TableIndex].OwnerId); AcpiTbReleaseOwnerId (TableIndex); return_ACPI_STATUS (Status); } Unlock: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Now we can parse the control methods. We always parse * them here for a sanity check, and if configured for * just-in-time parsing, we delete the control method * parse trees. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Table Object Initialization\n")); Status = AcpiDsInitializeObjects (TableIndex, Node); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Completed Table Object Initialization\n")); return_ACPI_STATUS (Status); }
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); }
ACPI_STATUS AcpiEvInitializeRegion ( ACPI_OPERAND_OBJECT *RegionObj, BOOLEAN AcpiNsLocked) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_ADR_SPACE_TYPE SpaceId; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *MethodNode; ACPI_NAME *RegNamePtr = (ACPI_NAME *) METHOD_NAME__REG; ACPI_OPERAND_OBJECT *RegionObj2; ACPI_FUNCTION_TRACE_U32 (EvInitializeRegion, AcpiNsLocked); if (!RegionObj) { return_ACPI_STATUS (AE_BAD_PARAMETER); } if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) { return_ACPI_STATUS (AE_OK); } RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); if (!RegionObj2) { return_ACPI_STATUS (AE_NOT_EXIST); } Node = RegionObj->Region.Node->Parent; SpaceId = RegionObj->Region.SpaceId; /* Setup defaults */ RegionObj->Region.Handler = NULL; RegionObj2->Extra.Method_REG = NULL; RegionObj->Common.Flags &= ~(AOPOBJ_SETUP_COMPLETE); RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; /* Find any "_REG" method associated with this region definition */ Status = AcpiNsSearchOneScope ( *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); if (ACPI_SUCCESS (Status)) { /* * The _REG method is optional and there can be only one per region * definition. This will be executed when the handler is attached * or removed */ RegionObj2->Extra.Method_REG = MethodNode; } /* * The following loop depends upon the root Node having no parent * ie: AcpiGbl_RootNode->ParentEntry being set to NULL */ while (Node) { /* Check to see if a handler exists */ HandlerObj = NULL; ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* Can only be a handler if the object exists */ switch (Node->Type) { case ACPI_TYPE_DEVICE: HandlerObj = ObjDesc->Device.Handler; break; case ACPI_TYPE_PROCESSOR: HandlerObj = ObjDesc->Processor.Handler; break; case ACPI_TYPE_THERMAL: HandlerObj = ObjDesc->ThermalZone.Handler; break; case ACPI_TYPE_METHOD: /* * If we are executing module level code, the original * Node's object was replaced by this Method object and we * saved the handler in the method object. * * See AcpiNsExecModuleCode */ if (ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) { HandlerObj = ObjDesc->Method.Dispatch.Handler; } break; default: /* Ignore other objects */ break; } while (HandlerObj) { /* Is this handler of the correct type? */ if (HandlerObj->AddressSpace.SpaceId == SpaceId) { /* Found correct handler */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler %p for region %p in obj %p\n", HandlerObj, RegionObj, ObjDesc)); Status = AcpiEvAttachRegion (HandlerObj, RegionObj, AcpiNsLocked); /* * Tell all users that this region is usable by * running the _REG method */ if (AcpiNsLocked) { Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); if (AcpiNsLocked) { Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } return_ACPI_STATUS (AE_OK); } /* Try next handler in the list */ HandlerObj = HandlerObj->AddressSpace.Next; } } /* This node does not have the handler we need; Pop up one level */ Node = Node->Parent; } /* If we get here, there is no handler for this region */ ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "No handler for RegionType %s(%X) (RegionObj %p)\n", AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); return_ACPI_STATUS (AE_NOT_EXIST); }
ACPI_STATUS AcpiNsWalkNamespace ( ACPI_OBJECT_TYPE Type, ACPI_HANDLE StartNode, UINT32 MaxDepth, UINT32 Flags, ACPI_WALK_CALLBACK PreOrderVisit, ACPI_WALK_CALLBACK PostOrderVisit, void *Context, void **ReturnValue) { ACPI_STATUS Status; ACPI_STATUS MutexStatus; ACPI_NAMESPACE_NODE *ChildNode; ACPI_NAMESPACE_NODE *ParentNode; ACPI_OBJECT_TYPE ChildType; UINT32 Level; BOOLEAN NodePreviouslyVisited = FALSE; ACPI_FUNCTION_TRACE (NsWalkNamespace); /* Special case for the namespace Root Node */ if (StartNode == ACPI_ROOT_OBJECT) { StartNode = AcpiGbl_RootNode; } /* Null child means "get first node" */ ParentNode = StartNode; ChildNode = AcpiNsGetNextNode (ParentNode, NULL); ChildType = ACPI_TYPE_ANY; Level = 1; /* * Traverse the tree of nodes until we bubble back up to where we * started. When Level is zero, the loop is done because we have * bubbled up to (and passed) the original parent handle (StartEntry) */ while (Level > 0 && ChildNode) { Status = AE_OK; /* Found next child, get the type if we are not searching for ANY */ if (Type != ACPI_TYPE_ANY) { ChildType = ChildNode->Type; } /* * Ignore all temporary namespace nodes (created during control * method execution) unless told otherwise. These temporary nodes * can cause a race condition because they can be deleted during * the execution of the user function (if the namespace is * unlocked before invocation of the user function.) Only the * debugger namespace dump will examine the temporary nodes. */ if ((ChildNode->Flags & ANOBJ_TEMPORARY) && !(Flags & ACPI_NS_WALK_TEMP_NODES)) { Status = AE_CTRL_DEPTH; } /* Type must match requested type */ else if (ChildType == Type) { /* * Found a matching node, invoke the user callback function. * Unlock the namespace if flag is set. */ if (Flags & ACPI_NS_WALK_UNLOCK) { MutexStatus = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (MutexStatus)) { return_ACPI_STATUS (MutexStatus); } } /* * Invoke the user function, either pre-order or post-order * or both. */ if (!NodePreviouslyVisited) { if (PreOrderVisit) { Status = PreOrderVisit (ChildNode, Level, Context, ReturnValue); } } else { if (PostOrderVisit) { Status = PostOrderVisit (ChildNode, Level, Context, ReturnValue); } } if (Flags & ACPI_NS_WALK_UNLOCK) { MutexStatus = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (MutexStatus)) { return_ACPI_STATUS (MutexStatus); } } switch (Status) { case AE_OK: case AE_CTRL_DEPTH: /* Just keep going */ break; case AE_CTRL_TERMINATE: /* Exit now, with OK status */ return_ACPI_STATUS (AE_OK); default: /* All others are valid exceptions */ return_ACPI_STATUS (Status); } } /* * Depth first search: Attempt to go down another level in the * namespace if we are allowed to. Don't go any further if we have * reached the caller specified maximum depth or if the user * function has specified that the maximum depth has been reached. */ if (!NodePreviouslyVisited && (Level < MaxDepth) && (Status != AE_CTRL_DEPTH)) { if (ChildNode->Child) { /* There is at least one child of this node, visit it */ Level++; ParentNode = ChildNode; ChildNode = AcpiNsGetNextNode (ParentNode, NULL); continue; } } /* No more children, re-visit this node */ if (!NodePreviouslyVisited) { NodePreviouslyVisited = TRUE; continue; } /* No more children, visit peers */ ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); if (ChildNode) { NodePreviouslyVisited = FALSE; } /* No peers, re-visit parent */ else { /* * No more children of this node (AcpiNsGetNextNode failed), go * back upwards in the namespace tree to the node's parent. */ Level--; ChildNode = ParentNode; ParentNode = AcpiNsGetParentNode (ParentNode); NodePreviouslyVisited = TRUE; } } /* Complete walk, not terminated by user function */ return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiGetObjectInfo ( ACPI_HANDLE Handle, ACPI_BUFFER *Buffer) { ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_DEVICE_INFO *Info; ACPI_DEVICE_INFO *ReturnInfo; ACPI_COMPATIBLE_ID_LIST *CidList = NULL; ACPI_SIZE Size; /* Parameter validation */ if (!Handle || !Buffer) { return (AE_BAD_PARAMETER); } Status = AcpiUtValidateBuffer (Buffer); if (ACPI_FAILURE (Status)) { return (Status); } Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DEVICE_INFO)); if (!Info) { return (AE_NO_MEMORY); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto Cleanup; } Node = AcpiNsMapHandleToNode (Handle); if (!Node) { (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); goto Cleanup; } /* Init return structure */ Size = sizeof (ACPI_DEVICE_INFO); Info->Type = Node->Type; Info->Name = Node->Name.Integer; Info->Valid = 0; Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* If not a device, we are all done */ if (Info->Type == ACPI_TYPE_DEVICE) { /* * Get extra info for ACPI Devices objects only: * Run the Device _HID, _UID, _CID, _STA, _ADR and _SxD methods. * * Note: none of these methods are required, so they may or may * not be present for this device. The Info->Valid bitfield is used * to indicate which methods were found and ran successfully. */ /* Execute the Device._HID method */ Status = AcpiUtExecute_HID (Node, &Info->HardwareId); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_HID; } /* Execute the Device._UID method */ Status = AcpiUtExecute_UID (Node, &Info->UniqueId); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_UID; } /* Execute the Device._CID method */ Status = AcpiUtExecute_CID (Node, &CidList); if (ACPI_SUCCESS (Status)) { Size += CidList->Size; Info->Valid |= ACPI_VALID_CID; } /* Execute the Device._STA method */ Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_STA; } /* Execute the Device._ADR method */ Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node, &Info->Address); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_ADR; } /* Execute the Device._SxD methods */ Status = AcpiUtExecute_Sxds (Node, Info->HighestDstates); if (ACPI_SUCCESS (Status)) { Info->Valid |= ACPI_VALID_SXDS; } } /* Validate/Allocate/Clear caller buffer */ Status = AcpiUtInitializeBuffer (Buffer, Size); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Populate the return buffer */ ReturnInfo = Buffer->Pointer; ACPI_MEMCPY (ReturnInfo, Info, sizeof (ACPI_DEVICE_INFO)); if (CidList) { ACPI_MEMCPY (&ReturnInfo->CompatibilityId, CidList, CidList->Size); } Cleanup: ACPI_FREE (Info); if (CidList) { ACPI_FREE (CidList); } return (Status); }
ACPI_STATUS AcpiTbLoadNamespace ( void) { ACPI_STATUS Status; UINT32 i; ACPI_TABLE_HEADER *NewDsdt; ACPI_TABLE_DESC *Table; UINT32 TablesLoaded = 0; UINT32 TablesFailed = 0; ACPI_FUNCTION_TRACE (TbLoadNamespace); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ Table = &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex]; if (!AcpiGbl_RootTableList.CurrentTableCount || !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_DSDT) || ACPI_FAILURE (AcpiTbValidateTable (Table))) { Status = AE_NO_ACPI_TABLES; goto UnlockAndExit; } /* * Save the DSDT pointer for simple access. This is the mapped memory * address. We must take care here because the address of the .Tables * array can change dynamically as tables are loaded at run-time. Note: * .Pointer field is not validated until after call to AcpiTbValidateTable. */ AcpiGbl_DSDT = Table->Pointer; /* * Optionally copy the entire DSDT to local memory (instead of simply * mapping it.) There are some BIOSs that corrupt or replace the original * DSDT, creating the need for this option. Default is FALSE, do not copy * the DSDT. */ if (AcpiGbl_CopyDsdtLocally) { NewDsdt = AcpiTbCopyDsdt (AcpiGbl_DsdtIndex); if (NewDsdt) { AcpiGbl_DSDT = NewDsdt; } } /* * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, sizeof (ACPI_TABLE_HEADER)); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); /* Load and parse tables */ Status = AcpiNsLoadTable (AcpiGbl_DsdtIndex, AcpiGbl_RootNode); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed")); TablesFailed++; } else { TablesLoaded++; } /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { Table = &AcpiGbl_RootTableList.Tables[i]; if (!AcpiGbl_RootTableList.Tables[i].Address || (!ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_SSDT) && !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_PSDT) && !ACPI_COMPARE_NAME (Table->Signature.Ascii, ACPI_SIG_OSDT)) || ACPI_FAILURE (AcpiTbValidateTable (Table))) { continue; } /* Ignore errors while loading tables, get as many as possible */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); Status = AcpiNsLoadTable (i, AcpiGbl_RootNode); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "(%4.4s:%8.8s) while loading table", Table->Signature.Ascii, Table->Pointer->OemTableId)); TablesFailed++; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", Table->Signature.Ascii, Table->Pointer->OemTableId)); } else { TablesLoaded++; } (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); } if (!TablesFailed) { ACPI_INFO ((AE_INFO, "%u ACPI AML tables successfully acquired and loaded", TablesLoaded)); } else { ACPI_ERROR ((AE_INFO, "%u table load failures, %u successful", TablesFailed, TablesLoaded)); /* Indicate at least one failure */ Status = AE_CTRL_TERMINATE; } UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (Status); }
void * AcpiOsAcquireObject ( ACPI_MEMORY_LIST *Cache) { ACPI_STATUS Status; void *Object; ACPI_FUNCTION_NAME (OsAcquireObject); if (!Cache) { return (NULL); } Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); if (ACPI_FAILURE (Status)) { return (NULL); } ACPI_MEM_TRACKING (Cache->Requests++); /* Check the cache first */ if (Cache->ListHead) { /* There is an object available, use it */ Object = Cache->ListHead; Cache->ListHead = ACPI_GET_DESCRIPTOR_PTR (Object); Cache->CurrentDepth--; ACPI_MEM_TRACKING (Cache->Hits++); ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Object %p from %s cache\n", Object, Cache->ListName)); Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); if (ACPI_FAILURE (Status)) { return (NULL); } /* Clear (zero) the previously used Object */ ACPI_MEMSET (Object, 0, Cache->ObjectSize); } else { /* The cache is empty, create a new object */ ACPI_MEM_TRACKING (Cache->TotalAllocated++); #ifdef ACPI_DBG_TRACK_ALLOCATIONS if ((Cache->TotalAllocated - Cache->TotalFreed) > Cache->MaxOccupied) { Cache->MaxOccupied = Cache->TotalAllocated - Cache->TotalFreed; } #endif /* Avoid deadlock with ACPI_ALLOCATE_ZEROED */ Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); if (ACPI_FAILURE (Status)) { return (NULL); } Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); if (!Object) { return (NULL); } } return (Object); }
ACPI_STATUS AcpiNsLoadTable ( UINT32 TableIndex, ACPI_NAMESPACE_NODE *Node) { ACPI_STATUS Status; ACPI_FUNCTION_TRACE (NsLoadTable); /* * Parse the table and load the namespace with all named * objects found within. Control methods are NOT parsed * at this time. In fact, the control methods cannot be * parsed until the entire namespace is loaded, because * if a control method makes a forward reference (call) * to another control method, we can't continue parsing * because we don't know how many arguments to parse next! */ Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* If table already loaded into namespace, just return */ if (AcpiTbIsTableLoaded (TableIndex)) { Status = AE_ALREADY_EXISTS; goto Unlock; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Loading table into namespace ****\n")); Status = AcpiTbAllocateOwnerId (TableIndex); if (ACPI_FAILURE (Status)) { goto Unlock; } Status = AcpiNsParseTable (TableIndex, Node); if (ACPI_SUCCESS (Status)) { AcpiTbSetTableLoadedFlag (TableIndex, TRUE); } else { (void) AcpiTbReleaseOwnerId (TableIndex); } Unlock: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Now we can parse the control methods. We always parse * them here for a sanity check, and if configured for * just-in-time parsing, we delete the control method * parse trees. */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Begin Table Object Initialization\n")); Status = AcpiDsInitializeObjects (TableIndex, Node); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "**** Completed Table Object Initialization\n")); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiUtTrackAllocation ( ACPI_DEBUG_MEM_BLOCK *Allocation, ACPI_SIZE Size, UINT8 AllocType, UINT32 Component, const char *Module, UINT32 Line) { ACPI_MEMORY_LIST *MemList; ACPI_DEBUG_MEM_BLOCK *Element; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); if (AcpiGbl_DisableMemTracking) { return_ACPI_STATUS (AE_OK); } MemList = AcpiGbl_GlobalList; Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Search the global list for this address to make sure it is not * already present. This will catch several kinds of problems. */ Element = AcpiUtFindAllocation (Allocation); if (Element == Allocation) { ACPI_ERROR ((AE_INFO, "UtTrackAllocation: Allocation (%p) already present in global list!", Allocation)); goto UnlockAndExit; } /* Fill in the instance data */ Allocation->Size = (UINT32) Size; Allocation->AllocType = AllocType; Allocation->Component = Component; Allocation->Line = Line; AcpiUtSafeStrncpy (Allocation->Module, (char *) Module, ACPI_MAX_MODULE_NAME); if (!Element) { /* Insert at list head */ if (MemList->ListHead) { ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation; } Allocation->Next = MemList->ListHead; Allocation->Previous = NULL; MemList->ListHead = Allocation; } else { /* Insert after element */ Allocation->Next = Element->Next; Allocation->Previous = Element; if (Element->Next) { (Element->Next)->Previous = Allocation; } Element->Next = Allocation; } UnlockAndExit: Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); return_ACPI_STATUS (Status); }
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_DEVICE_ID_LIST *Cid; UINT32 i; BOOLEAN Found; int Match; 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); } Match = ACPI_STRCMP (Hid->String, Info->Hid); ACPI_FREE (Hid); if (!Match) { /* * 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_STRCMP (Cid->Ids[i].String, Info->Hid) == 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); }
static ACPI_STATUS AcpiUtRemoveAllocation ( ACPI_DEBUG_MEM_BLOCK *Allocation, UINT32 Component, const char *Module, UINT32 Line) { ACPI_MEMORY_LIST *MemList; ACPI_STATUS Status; ACPI_FUNCTION_NAME (UtRemoveAllocation); if (AcpiGbl_DisableMemTracking) { return (AE_OK); } MemList = AcpiGbl_GlobalList; if (NULL == MemList->ListHead) { /* No allocations! */ ACPI_ERROR ((Module, Line, "Empty allocation list, nothing to free!")); return (AE_OK); } Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); if (ACPI_FAILURE (Status)) { return (Status); } /* Unlink */ if (Allocation->Previous) { (Allocation->Previous)->Next = Allocation->Next; } else { MemList->ListHead = Allocation->Next; } if (Allocation->Next) { (Allocation->Next)->Previous = Allocation->Previous; } ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", &Allocation->UserSpace, Allocation->Size)); /* Mark the segment as deleted */ memset (&Allocation->UserSpace, 0xEA, Allocation->Size); Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); return (Status); }
ACPI_STATUS AcpiExLoadOp ( ACPI_OPERAND_OBJECT *ObjDesc, ACPI_OPERAND_OBJECT *Target, ACPI_WALK_STATE *WalkState) { ACPI_OPERAND_OBJECT *DdbHandle; ACPI_TABLE_HEADER *TableHeader; ACPI_TABLE_HEADER *Table; UINT32 TableIndex; ACPI_STATUS Status; UINT32 Length; ACPI_FUNCTION_TRACE (ExLoadOp); /* Source Object can be either an OpRegion or a Buffer/Field */ switch (ObjDesc->Common.Type) { case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load table from Region %p\n", ObjDesc)); /* Region must be SystemMemory (from ACPI spec) */ if (ObjDesc->Region.SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) { return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* * If the Region Address and Length have not been previously * evaluated, evaluate them now and save the results. */ if (!(ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)) { Status = AcpiDsGetRegionArguments (ObjDesc); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* Get the table header first so we can get the table length */ TableHeader = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); if (!TableHeader) { return_ACPI_STATUS (AE_NO_MEMORY); } Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), ACPI_CAST_PTR (UINT8, TableHeader)); Length = TableHeader->Length; ACPI_FREE (TableHeader); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Must have at least an ACPI table header */ if (Length < sizeof (ACPI_TABLE_HEADER)) { return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } /* * The original implementation simply mapped the table, with no copy. * However, the memory region is not guaranteed to remain stable and * we must copy the table to a local buffer. For example, the memory * region is corrupted after suspend on some machines. Dynamically * loaded tables are usually small, so this overhead is minimal. * * The latest implementation (5/2009) does not use a mapping at all. * We use the low-level operation region interface to read the table * instead of the obvious optimization of using a direct mapping. * This maintains a consistent use of operation regions across the * entire subsystem. This is important if additional processing must * be performed in the (possibly user-installed) operation region * handler. For example, AcpiExec and ASLTS depend on this. */ /* Allocate a buffer for the table */ Table = ACPI_ALLOCATE (Length); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } /* Read the entire table */ Status = AcpiExRegionRead (ObjDesc, Length, ACPI_CAST_PTR (UINT8, Table)); if (ACPI_FAILURE (Status)) { ACPI_FREE (Table); return_ACPI_STATUS (Status); } break; case ACPI_TYPE_BUFFER: /* Buffer or resolved RegionField */ ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Load table from Buffer or Field %p\n", ObjDesc)); /* Must have at least an ACPI table header */ if (ObjDesc->Buffer.Length < sizeof (ACPI_TABLE_HEADER)) { return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } /* Get the actual table length from the table header */ TableHeader = ACPI_CAST_PTR ( ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); Length = TableHeader->Length; /* Table cannot extend beyond the buffer */ if (Length > ObjDesc->Buffer.Length) { return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); } if (Length < sizeof (ACPI_TABLE_HEADER)) { return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); } /* * Copy the table from the buffer because the buffer could be * modified or even deleted in the future */ Table = ACPI_ALLOCATE (Length); if (!Table) { return_ACPI_STATUS (AE_NO_MEMORY); } memcpy (Table, TableHeader, Length); break; default: return_ACPI_STATUS (AE_AML_OPERAND_TYPE); } /* Install the new table into the local data structures */ ACPI_INFO (("Dynamic OEM Table Load:")); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, TRUE, TRUE, &TableIndex); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); if (ACPI_FAILURE (Status)) { /* Delete allocated table buffer */ ACPI_FREE (Table); return_ACPI_STATUS (Status); } /* * Note: Now table is "INSTALLED", it must be validated before * loading. */ Status = AcpiTbValidateTable ( &AcpiGbl_RootTableList.Tables[TableIndex]); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Add the table to the namespace. * * Note: Load the table objects relative to the root of the namespace. * This appears to go against the ACPI specification, but we do it for * compatibility with other ACPI implementations. */ Status = AcpiExAddTable (TableIndex, AcpiGbl_RootNode, &DdbHandle); if (ACPI_FAILURE (Status)) { /* On error, TablePtr was deallocated above */ return_ACPI_STATUS (Status); } /* Store the DdbHandle into the Target operand */ Status = AcpiExStore (DdbHandle, Target, WalkState); if (ACPI_FAILURE (Status)) { (void) AcpiExUnloadTable (DdbHandle); /* TablePtr was deallocated above */ AcpiUtRemoveReference (DdbHandle); return_ACPI_STATUS (Status); } /* Remove the reference by added by AcpiExStore above */ AcpiUtRemoveReference (DdbHandle); /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, AcpiGbl_TableHandlerContext); } return_ACPI_STATUS (Status); }
void AcpiUtDumpAllocations ( UINT32 Component, const char *Module) { ACPI_DEBUG_MEM_BLOCK *Element; ACPI_DESCRIPTOR *Descriptor; UINT32 NumOutstanding = 0; UINT8 DescriptorType; ACPI_FUNCTION_TRACE (UtDumpAllocations); if (AcpiGbl_DisableMemTracking) { return_VOID; } /* * Walk the allocation list. */ if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) { return_VOID; } if (!AcpiGbl_GlobalList) { goto Exit; } Element = AcpiGbl_GlobalList->ListHead; while (Element) { if ((Element->Component & Component) && ((Module == NULL) || (0 == strcmp (Module, Element->Module)))) { Descriptor = ACPI_CAST_PTR ( ACPI_DESCRIPTOR, &Element->UserSpace); if (Element->Size < sizeof (ACPI_COMMON_DESCRIPTOR)) { AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u " "[Not a Descriptor - too small]\n", Descriptor, Element->Size, Element->Module, Element->Line); } else { /* Ignore allocated objects that are in a cache */ if (ACPI_GET_DESCRIPTOR_TYPE (Descriptor) != ACPI_DESC_TYPE_CACHED) { AcpiOsPrintf ("%p Length 0x%04X %9.9s-%4.4u [%s] ", Descriptor, Element->Size, Element->Module, Element->Line, AcpiUtGetDescriptorName (Descriptor)); /* Optional object hex dump */ if (AcpiGbl_VerboseLeakDump) { AcpiOsPrintf ("\n"); AcpiUtDumpBuffer ((UINT8 *) Descriptor, Element->Size, DB_BYTE_DISPLAY, 0); } /* Validate the descriptor type using Type field and length */ DescriptorType = 0; /* Not a valid descriptor type */ switch (ACPI_GET_DESCRIPTOR_TYPE (Descriptor)) { case ACPI_DESC_TYPE_OPERAND: if (Element->Size == sizeof (ACPI_OPERAND_OBJECT)) { DescriptorType = ACPI_DESC_TYPE_OPERAND; } break; case ACPI_DESC_TYPE_PARSER: if (Element->Size == sizeof (ACPI_PARSE_OBJECT)) { DescriptorType = ACPI_DESC_TYPE_PARSER; } break; case ACPI_DESC_TYPE_NAMED: if (Element->Size == sizeof (ACPI_NAMESPACE_NODE)) { DescriptorType = ACPI_DESC_TYPE_NAMED; } break; default: break; } /* Display additional info for the major descriptor types */ switch (DescriptorType) { case ACPI_DESC_TYPE_OPERAND: AcpiOsPrintf ("%12.12s RefCount 0x%04X\n", AcpiUtGetTypeName (Descriptor->Object.Common.Type), Descriptor->Object.Common.ReferenceCount); break; case ACPI_DESC_TYPE_PARSER: AcpiOsPrintf ("AmlOpcode 0x%04hX\n", Descriptor->Op.Asl.AmlOpcode); break; case ACPI_DESC_TYPE_NAMED: AcpiOsPrintf ("%4.4s\n", AcpiUtGetNodeName (&Descriptor->Node)); break; default: AcpiOsPrintf ( "\n"); break; } } } NumOutstanding++; } Element = Element->Next; } Exit: (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); /* Print summary */ if (!NumOutstanding) { ACPI_INFO (("No outstanding allocations")); } else { ACPI_ERROR ((AE_INFO, "%u (0x%X) Outstanding cache allocations", NumOutstanding, NumOutstanding)); } return_VOID; }
static ACPI_STATUS AcpiUtTrackAllocation ( ACPI_DEBUG_MEM_BLOCK *Allocation, ACPI_SIZE Size, UINT8 AllocType, UINT32 Component, char *Module, UINT32 Line) { ACPI_MEMORY_LIST *MemList; ACPI_DEBUG_MEM_BLOCK *Element; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE_PTR (UtTrackAllocation, Allocation); MemList = AcpiGbl_GlobalList; Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Search list for this address to make sure it is not already on the list. * This will catch several kinds of problems. */ Element = AcpiUtFindAllocation (Allocation); if (Element) { ACPI_ERROR ((AE_INFO, "UtTrackAllocation: Allocation already present in list! (%p)", Allocation)); ACPI_ERROR ((AE_INFO, "Element %p Address %p", Element, Allocation)); goto UnlockAndExit; } /* Fill in the instance data. */ Allocation->Size = (UINT32) Size; Allocation->AllocType = AllocType; Allocation->Component = Component; Allocation->Line = Line; ACPI_STRNCPY (Allocation->Module, Module, ACPI_MAX_MODULE_NAME); Allocation->Module[ACPI_MAX_MODULE_NAME-1] = 0; /* Insert at list head */ if (MemList->ListHead) { ((ACPI_DEBUG_MEM_BLOCK *)(MemList->ListHead))->Previous = Allocation; } Allocation->Next = MemList->ListHead; Allocation->Previous = NULL; MemList->ListHead = Allocation; UnlockAndExit: Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); return_ACPI_STATUS (Status); }
void AcpiEvUpdateGpes ( ACPI_OWNER_ID TableOwnerId) { ACPI_GPE_XRUPT_INFO *GpeXruptInfo; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_WALK_INFO WalkInfo; ACPI_STATUS Status = AE_OK; /* * Find any _Lxx/_Exx GPE methods that have just been loaded. * * Any GPEs that correspond to new _Lxx/_Exx methods are immediately * enabled. * * Examine the namespace underneath each GpeDevice within the * GpeBlock lists. */ Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); if (ACPI_FAILURE (Status)) { return; } WalkInfo.Count = 0; WalkInfo.OwnerId = TableOwnerId; WalkInfo.ExecuteByOwnerId = TRUE; /* Walk the interrupt level descriptor list */ GpeXruptInfo = AcpiGbl_GpeXruptListHead; while (GpeXruptInfo) { /* Walk all Gpe Blocks attached to this interrupt level */ GpeBlock = GpeXruptInfo->GpeBlockListHead; while (GpeBlock) { WalkInfo.GpeBlock = GpeBlock; WalkInfo.GpeDevice = GpeBlock->Node; Status = AcpiNsWalkNamespace (ACPI_TYPE_METHOD, WalkInfo.GpeDevice, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, AcpiEvMatchGpeMethod, NULL, &WalkInfo, NULL); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While decoding _Lxx/_Exx methods")); } GpeBlock = GpeBlock->Next; } GpeXruptInfo = GpeXruptInfo->Next; } if (WalkInfo.Count) { ACPI_INFO ((AE_INFO, "Enabled %u new GPEs", WalkInfo.Count)); } (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); return; }
static ACPI_STATUS AcpiTbLoadNamespace ( void) { ACPI_STATUS Status; UINT32 i; ACPI_TABLE_HEADER *NewDsdt; ACPI_FUNCTION_TRACE (TbLoadNamespace); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ if (!AcpiGbl_RootTableList.CurrentTableCount || !ACPI_COMPARE_NAME ( &(AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Signature), ACPI_SIG_DSDT) || ACPI_FAILURE (AcpiTbValidateTable ( &AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]))) { Status = AE_NO_ACPI_TABLES; goto UnlockAndExit; } /* * Save the DSDT pointer for simple access. This is the mapped memory * address. We must take care here because the address of the .Tables * array can change dynamically as tables are loaded at run-time. Note: * .Pointer field is not validated until after call to AcpiTbValidateTable. */ AcpiGbl_DSDT = AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer; /* * Optionally copy the entire DSDT to local memory (instead of simply * mapping it.) There are some BIOSs that corrupt or replace the original * DSDT, creating the need for this option. Default is FALSE, do not copy * the DSDT. */ if (AcpiGbl_CopyDsdtLocally) { NewDsdt = AcpiTbCopyDsdt (ACPI_TABLE_INDEX_DSDT); if (NewDsdt) { AcpiGbl_DSDT = NewDsdt; } } /* * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ ACPI_MEMCPY (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, sizeof (ACPI_TABLE_HEADER)); (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); /* Load and parse tables */ Status = AcpiNsLoadTable (ACPI_TABLE_INDEX_DSDT, AcpiGbl_RootNode); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if ((!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), ACPI_SIG_SSDT) && !ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature), ACPI_SIG_PSDT)) || ACPI_FAILURE (AcpiTbValidateTable ( &AcpiGbl_RootTableList.Tables[i]))) { continue; } /* Ignore errors while loading tables, get as many as possible */ (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); (void) AcpiNsLoadTable (i, AcpiGbl_RootNode); (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); } ACPI_INFO ((AE_INFO, "All ACPI Tables successfully acquired")); UnlockAndExit: (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiEvGpeInitialize ( void) { UINT32 RegisterCount0 = 0; UINT32 RegisterCount1 = 0; UINT32 GpeNumberMax = 0; ACPI_STATUS Status; ACPI_FUNCTION_TRACE (EvGpeInitialize); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "Initializing General Purpose Events (GPEs):\n")); Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* * Initialize the GPE Block(s) defined in the FADT * * Why the GPE register block lengths are divided by 2: From the ACPI * Spec, section "General-Purpose Event Registers", we have: * * "Each register block contains two registers of equal length * GPEx_STS and GPEx_EN (where x is 0 or 1). The length of the * GPE0_STS and GPE0_EN registers is equal to half the GPE0_LEN * The length of the GPE1_STS and GPE1_EN registers is equal to * half the GPE1_LEN. If a generic register block is not supported * then its respective block pointer and block length values in the * FADT table contain zeros. The GPE0_LEN and GPE1_LEN do not need * to be the same size." */ /* * Determine the maximum GPE number for this machine. * * Note: both GPE0 and GPE1 are optional, and either can exist without * the other. * * If EITHER the register length OR the block address are zero, then that * particular block is not supported. */ if (AcpiGbl_FADT.Gpe0BlockLength && AcpiGbl_FADT.XGpe0Block.Address) { /* GPE block 0 exists (has both length and address > 0) */ RegisterCount0 = (UINT16) (AcpiGbl_FADT.Gpe0BlockLength / 2); GpeNumberMax = (RegisterCount0 * ACPI_GPE_REGISTER_WIDTH) - 1; /* Install GPE Block 0 */ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, &AcpiGbl_FADT.XGpe0Block, RegisterCount0, 0, AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[0]); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create GPE Block 0")); } } if (AcpiGbl_FADT.Gpe1BlockLength && AcpiGbl_FADT.XGpe1Block.Address) { /* GPE block 1 exists (has both length and address > 0) */ RegisterCount1 = (UINT16) (AcpiGbl_FADT.Gpe1BlockLength / 2); /* Check for GPE0/GPE1 overlap (if both banks exist) */ if ((RegisterCount0) && (GpeNumberMax >= AcpiGbl_FADT.Gpe1Base)) { ACPI_ERROR ((AE_INFO, "GPE0 block (GPE 0 to %u) overlaps the GPE1 block " "(GPE %u to %u) - Ignoring GPE1", GpeNumberMax, AcpiGbl_FADT.Gpe1Base, AcpiGbl_FADT.Gpe1Base + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1))); /* Ignore GPE1 block by setting the register count to zero */ RegisterCount1 = 0; } else { /* Install GPE Block 1 */ Status = AcpiEvCreateGpeBlock (AcpiGbl_FadtGpeDevice, &AcpiGbl_FADT.XGpe1Block, RegisterCount1, AcpiGbl_FADT.Gpe1Base, AcpiGbl_FADT.SciInterrupt, &AcpiGbl_GpeFadtBlocks[1]); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not create GPE Block 1")); } /* * GPE0 and GPE1 do not have to be contiguous in the GPE number * space. However, GPE0 always starts at GPE number zero. */ GpeNumberMax = AcpiGbl_FADT.Gpe1Base + ((RegisterCount1 * ACPI_GPE_REGISTER_WIDTH) - 1); } } /* Exit if there are no GPE registers */ if ((RegisterCount0 + RegisterCount1) == 0) { /* GPEs are not required by ACPI, this is OK */ ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "There are no GPE blocks defined in the FADT\n")); Status = AE_OK; goto Cleanup; } Cleanup: (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiUnloadParentTable ( ACPI_HANDLE Object) { ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); ACPI_STATUS Status = AE_NOT_EXIST; ACPI_OWNER_ID OwnerId; UINT32 i; ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); /* Parameter validation */ if (!Object) { return_ACPI_STATUS (AE_BAD_PARAMETER); } /* * The node OwnerId is currently the same as the parent table ID. * However, this could change in the future. */ OwnerId = Node->OwnerId; if (!OwnerId) { /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ return_ACPI_STATUS (AE_TYPE); } /* Must acquire the interpreter lock during this operation */ Status = AcpiUtAcquireMutex (ACPI_MTX_INTERPRETER); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Find the table in the global table list */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) { continue; } /* * Allow unload of SSDT and OEMx tables only. Do not allow unload * of the DSDT. No other types of tables should get here, since * only these types can contain AML and thus are the only types * that can create namespace objects. */ if (ACPI_COMPARE_NAME ( AcpiGbl_RootTableList.Tables[i].Signature.Ascii, ACPI_SIG_DSDT)) { Status = AE_TYPE; break; } /* Ensure the table is actually loaded */ if (!AcpiTbIsTableLoaded (i)) { Status = AE_NOT_EXIST; break; } /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_UNLOAD, AcpiGbl_RootTableList.Tables[i].Pointer, AcpiGbl_TableHandlerContext); } /* * Delete all namespace objects owned by this table. Note that * these objects can appear anywhere in the namespace by virtue * of the AML "Scope" operator. Thus, we need to track ownership * by an ID, not simply a position within the hierarchy. */ Status = AcpiTbDeleteNamespaceByOwner (i); if (ACPI_FAILURE (Status)) { break; } Status = AcpiTbReleaseOwnerId (i); AcpiTbSetTableLoadedFlag (i, FALSE); break; } (void) AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); return_ACPI_STATUS (Status); }
void AcpiExStopTraceMethod ( ACPI_NAMESPACE_NODE *MethodNode, ACPI_OPERAND_OBJECT *ObjDesc, ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; char *Pathname = NULL; BOOLEAN Enabled; ACPI_FUNCTION_NAME (ExStopTraceMethod); if (MethodNode) { Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto ExitPath; } Enabled = AcpiExInterpreterTraceEnabled (NULL); (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (Enabled) { ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); } Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { goto ExitPath; } /* Check whether the tracer should be stopped */ if (AcpiGbl_TraceMethodObject == ObjDesc) { /* Disable further tracing if type is one-shot */ if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) { AcpiGbl_TraceMethodName = NULL; } AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; AcpiGbl_TraceMethodObject = NULL; } (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); ExitPath: if (Pathname) { ACPI_FREE (Pathname); } }