void AcpiUtDumpAllocations ( UINT32 Component, const 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); }
void acpi_ev_update_gpes(acpi_owner_id table_owner_id) { struct acpi_gpe_xrupt_info *gpe_xrupt_info; struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_walk_info walk_info; 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 gpe_device within the * gpe_block lists. */ status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); if (ACPI_FAILURE(status)) { return; } walk_info.count = 0; walk_info.owner_id = table_owner_id; walk_info.execute_by_owner_id = TRUE; /* Walk the interrupt level descriptor list */ gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; while (gpe_xrupt_info) { /* Walk all Gpe Blocks attached to this interrupt level */ gpe_block = gpe_xrupt_info->gpe_block_list_head; while (gpe_block) { walk_info.gpe_block = gpe_block; walk_info.gpe_device = gpe_block->node; status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, walk_info.gpe_device, ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, acpi_ev_match_gpe_method, NULL, &walk_info, NULL); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "While decoding _Lxx/_Exx methods")); } gpe_block = gpe_block->next; } gpe_xrupt_info = gpe_xrupt_info->next; } if (walk_info.count) { ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count)); } (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); return; }
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; } Element = AcpiGbl_GlobalList->ListHead; while (Element) { if ((Element->Component & Component) && ((Module == NULL) || (0 == ACPI_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-%u " "[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-%u [%s] ", Descriptor, Element->Size, Element->Module, Element->Line, AcpiUtGetDescriptorName (Descriptor)); /* 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; } (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); /* Print summary */ if (!NumOutstanding) { ACPI_INFO ((AE_INFO, "No outstanding allocations")); } else { ACPI_ERROR ((AE_INFO, "%u(0x%X) Outstanding allocations", NumOutstanding, NumOutstanding)); } return_VOID; }
int ACPI_SYSTEM_XFACE main ( int argc, char **argv) { ACPI_STATUS Status; UINT32 InitFlags; ACPI_TABLE_HEADER *Table = NULL; UINT32 TableCount; AE_TABLE_DESC *TableDesc; ACPI_DEBUG_INITIALIZE (); /* For debug version only */ signal (SIGINT, AeCtrlCHandler); /* Init debug globals */ AcpiDbgLevel = ACPI_NORMAL_DEFAULT; AcpiDbgLayer = 0xFFFFFFFF; /* Init ACPICA and start debugger thread */ Status = AcpiInitializeSubsystem (); AE_CHECK_OK (AcpiInitializeSubsystem, Status); if (ACPI_FAILURE (Status)) { goto ErrorExit; } printf (ACPI_COMMON_SIGNON (ACPIEXEC_NAME)); if (argc < 2) { usage (); (void) AcpiOsTerminate (); return (0); } /* Get the command line options */ if (AeDoOptions (argc, argv)) { goto ErrorExit; } /* The remaining arguments are filenames for ACPI tables */ if (!argv[AcpiGbl_Optind]) { goto EnterDebugger; } AcpiGbl_CstyleDisassembly = FALSE; /* Not supported for AcpiExec */ TableCount = 0; /* Get each of the ACPI table files on the command line */ while (argv[AcpiGbl_Optind]) { /* Get one entire table */ Status = AcpiUtReadTableFromFile (argv[AcpiGbl_Optind], &Table); if (ACPI_FAILURE (Status)) { printf ("**** Could not get table from file %s, %s\n", argv[AcpiGbl_Optind], AcpiFormatException (Status)); goto ErrorExit; } /* Ignore non-AML tables, we can't use them. Except for an FADT */ if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_FADT) && !AcpiUtIsAmlTable (Table)) { ACPI_INFO ((AE_INFO, "Table [%4.4s] is not an AML table, ignoring", Table->Signature)); AcpiOsFree (Table); } else { /* Allocate and link a table descriptor */ TableDesc = AcpiOsAllocate (sizeof (AE_TABLE_DESC)); TableDesc->Table = Table; TableDesc->Next = AeTableListHead; AeTableListHead = TableDesc; TableCount++; } AcpiGbl_Optind++; } printf ("\n"); /* Build a local RSDT with all tables and let ACPICA process the RSDT */ Status = AeBuildLocalTables (TableCount, AeTableListHead); if (ACPI_FAILURE (Status)) { goto ErrorExit; } Status = AeInstallTables (); if (ACPI_FAILURE (Status)) { printf ("**** Could not load ACPI tables, %s\n", AcpiFormatException (Status)); goto EnterDebugger; } /* * Install most of the handlers. * Override some default region handlers, especially SystemMemory */ Status = AeInstallEarlyHandlers (); if (ACPI_FAILURE (Status)) { goto EnterDebugger; } /* Setup initialization flags for ACPICA */ InitFlags = (ACPI_NO_HANDLER_INIT | ACPI_NO_ACPI_ENABLE); if (AcpiGbl_DbOpt_NoIniMethods) { InitFlags |= (ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT); } /* * Main initialization for ACPICA subsystem * TBD: Need a way to call this after the ACPI table "LOAD" command */ Status = AcpiEnableSubsystem (InitFlags); if (ACPI_FAILURE (Status)) { printf ("**** Could not EnableSubsystem, %s\n", AcpiFormatException (Status)); goto EnterDebugger; } /* * Install handlers for "device driver" space IDs (EC,SMBus, etc.) * and fixed event handlers */ AeInstallLateHandlers (); /* Finish the ACPICA initialization */ Status = AcpiInitializeObjects (InitFlags); if (ACPI_FAILURE (Status)) { printf ("**** Could not InitializeObjects, %s\n", AcpiFormatException (Status)); goto EnterDebugger; } AeMiscellaneousTests (); EnterDebugger: /* Exit if error above and we are in one of the batch modes */ if (ACPI_FAILURE (Status) && (AcpiGbl_ExecutionMode > 0)) { goto ErrorExit; } /* Run a batch command or enter the command loop */ switch (AcpiGbl_ExecutionMode) { default: case AE_MODE_COMMAND_LOOP: AcpiDbUserCommands (ACPI_DEBUGGER_COMMAND_PROMPT, NULL); break; case AE_MODE_BATCH_MULTIPLE: AcpiDbRunBatchMode (); break; case AE_MODE_BATCH_SINGLE: AcpiDbExecute (BatchBuffer, NULL, NULL, EX_NO_SINGLE_STEP); Status = AcpiTerminate (); break; } return (0); ErrorExit: (void) AcpiOsTerminate (); return (-1); }
ACPI_STATUS AcpiPsParseAml ( ACPI_WALK_STATE *WalkState) { ACPI_STATUS Status; ACPI_THREAD_STATE *Thread; ACPI_THREAD_STATE *PrevWalkList = AcpiGbl_CurrentWalkList; ACPI_WALK_STATE *PreviousWalkState; ACPI_FUNCTION_TRACE (PsParseAml); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Entered with WalkState=%p Aml=%p size=%X\n", WalkState, WalkState->ParserState.Aml, WalkState->ParserState.AmlSize)); if (!WalkState->ParserState.Aml) { return_ACPI_STATUS (AE_NULL_OBJECT); } /* Create and initialize a new thread state */ Thread = AcpiUtCreateThreadState (); if (!Thread) { if (WalkState->MethodDesc) { /* Executing a control method - additional cleanup */ AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); } AcpiDsDeleteWalkState (WalkState); return_ACPI_STATUS (AE_NO_MEMORY); } WalkState->Thread = Thread; /* * If executing a method, the starting SyncLevel is this method's * SyncLevel */ if (WalkState->MethodDesc) { WalkState->Thread->CurrentSyncLevel = WalkState->MethodDesc->Method.SyncLevel; } AcpiDsPushWalkState (WalkState, Thread); /* * This global allows the AML debugger to get a handle to the currently * executing control method. */ AcpiGbl_CurrentWalkList = Thread; /* * Execute the walk loop as long as there is a valid Walk State. This * handles nested control method invocations without recursion. */ ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "State=%p\n", WalkState)); Status = AE_OK; while (WalkState) { if (ACPI_SUCCESS (Status)) { /* * The ParseLoop executes AML until the method terminates * or calls another method. */ Status = AcpiPsParseLoop (WalkState); } ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Completed one call to walk loop, %s State=%p\n", AcpiFormatException (Status), WalkState)); if (Status == AE_CTRL_TRANSFER) { /* * A method call was detected. * Transfer control to the called control method */ Status = AcpiDsCallControlMethod (Thread, WalkState, NULL); if (ACPI_FAILURE (Status)) { Status = AcpiDsMethodError (Status, WalkState); } /* * If the transfer to the new method method call worked, a new walk * state was created -- get it */ WalkState = AcpiDsGetCurrentWalkState (Thread); continue; } else if (Status == AE_CTRL_TERMINATE) { Status = AE_OK; } else if ((Status != AE_OK) && (WalkState->MethodDesc)) { /* Either the method parse or actual execution failed */ ACPI_ERROR_METHOD ("Method parse/execution failed", WalkState->MethodNode, NULL, Status); /* Check for possible multi-thread reentrancy problem */ if ((Status == AE_ALREADY_EXISTS) && (!WalkState->MethodDesc->Method.Mutex)) { 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. The probable cause is * that the method cannot handle reentrancy. * * The method is marked NotSerialized, but it tried to create * a named object, causing the second thread entrance to fail. * Workaround this problem by marking the method permanently * as Serialized. */ WalkState->MethodDesc->Method.MethodFlags |= AML_METHOD_SERIALIZED; WalkState->MethodDesc->Method.SyncLevel = 0; } } /* We are done with this walk, move on to the parent if any */ WalkState = AcpiDsPopWalkState (Thread); /* Reset the current scope to the beginning of scope stack */ AcpiDsScopeStackClear (WalkState); /* * If we just returned from the execution of a control method or if we * encountered an error during the method parse phase, there's lots of * cleanup to do */ if (((WalkState->ParseFlags & ACPI_PARSE_MODE_MASK) == ACPI_PARSE_EXECUTE) || (ACPI_FAILURE (Status))) { AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState); } /* Delete this walk state and all linked control states */ AcpiPsCleanupScope (&WalkState->ParserState); PreviousWalkState = WalkState; ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "ReturnValue=%p, ImplicitValue=%p State=%p\n", WalkState->ReturnDesc, WalkState->ImplicitReturnObj, WalkState)); /* Check if we have restarted a preempted walk */ WalkState = AcpiDsGetCurrentWalkState (Thread); if (WalkState) { if (ACPI_SUCCESS (Status)) { /* * There is another walk state, restart it. * If the method return value is not used by the parent, * The object is deleted */ if (!PreviousWalkState->ReturnDesc) { /* * In slack mode execution, if there is no return value * we should implicitly return zero (0) as a default value. */ if (AcpiGbl_EnableInterpreterSlack && !PreviousWalkState->ImplicitReturnObj) { PreviousWalkState->ImplicitReturnObj = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); if (!PreviousWalkState->ImplicitReturnObj) { return_ACPI_STATUS (AE_NO_MEMORY); } PreviousWalkState->ImplicitReturnObj->Integer.Value = 0; } /* Restart the calling control method */ Status = AcpiDsRestartControlMethod (WalkState, PreviousWalkState->ImplicitReturnObj); } else { /* * We have a valid return value, delete any implicit * return value. */ AcpiDsClearImplicitReturn (PreviousWalkState); Status = AcpiDsRestartControlMethod (WalkState, PreviousWalkState->ReturnDesc); } if (ACPI_SUCCESS (Status)) { WalkState->WalkType |= ACPI_WALK_METHOD_RESTART; } } else { /* On error, delete any return object or implicit return */ AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); AcpiDsClearImplicitReturn (PreviousWalkState); } } /* * Just completed a 1st-level method, save the final internal return * value (if any) */ else if (PreviousWalkState->CallerReturnDesc) { if (PreviousWalkState->ImplicitReturnObj) { *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ImplicitReturnObj; } else { /* NULL if no return value */ *(PreviousWalkState->CallerReturnDesc) = PreviousWalkState->ReturnDesc; } } else { if (PreviousWalkState->ReturnDesc) { /* Caller doesn't want it, must delete it */ AcpiUtRemoveReference (PreviousWalkState->ReturnDesc); } if (PreviousWalkState->ImplicitReturnObj) { /* Caller doesn't want it, must delete it */ AcpiUtRemoveReference (PreviousWalkState->ImplicitReturnObj); } } AcpiDsDeleteWalkState (PreviousWalkState); } /* Normal exit */ AcpiExReleaseAllMutexes (Thread); AcpiUtDeleteGenericState (ACPI_CAST_PTR (ACPI_GENERIC_STATE, Thread)); AcpiGbl_CurrentWalkList = PrevWalkList; 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; }
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); }
/******************************************************************************* * * FUNCTION: acpi_tb_load_namespace * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in * the RSDT/XSDT. * ******************************************************************************/ acpi_status acpi_tb_load_namespace(void) { acpi_status status; u32 i; struct acpi_table_header *new_dsdt; struct acpi_table_desc *table; u32 tables_loaded = 0; u32 tables_failed = 0; ACPI_FUNCTION_TRACE(tb_load_namespace); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ table = &acpi_gbl_root_table_list.tables[acpi_gbl_dsdt_index]; if (!acpi_gbl_root_table_list.current_table_count || !ACPI_COMPARE_NAME(table->signature.ascii, ACPI_SIG_DSDT) || ACPI_FAILURE(acpi_tb_validate_table(table))) { status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } /* * 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 acpi_tb_validate_table. */ acpi_gbl_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 (acpi_gbl_copy_dsdt_locally) { new_dsdt = acpi_tb_copy_dsdt(acpi_gbl_dsdt_index); if (new_dsdt) { acpi_gbl_DSDT = new_dsdt; } } /* * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ memcpy(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, sizeof(struct acpi_table_header)); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); /* Load and parse tables */ status = acpi_ns_load_table(acpi_gbl_dsdt_index, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "[DSDT] table load failed")); tables_failed++; } else { tables_loaded++; } /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { table = &acpi_gbl_root_table_list.tables[i]; if (!acpi_gbl_root_table_list.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(acpi_tb_validate_table(table))) { continue; } /* Ignore errors while loading tables, get as many as possible */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); status = acpi_ns_load_table(i, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "(%4.4s:%8.8s) while loading table", table->signature.ascii, table->pointer->oem_table_id)); tables_failed++; 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->oem_table_id)); } else { tables_loaded++; } (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } if (!tables_failed) { ACPI_INFO(("%u ACPI AML tables successfully acquired and loaded\n", tables_loaded)); } else { ACPI_ERROR((AE_INFO, "%u table load failures, %u successful", tables_failed, tables_loaded)); /* Indicate at least one failure */ status = AE_CTRL_TERMINATE; } unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 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; }
static ACPI_STATUS InitializeFullAcpica (void) { ACPI_STATUS Status; /* Initialize the ACPICA subsystem */ AcpiGbl_OverrideDefaultRegionHandlers = TRUE; Status = AcpiInitializeSubsystem (); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA")); return (Status); } /* Initialize the ACPICA Table Manager and get all ACPI tables */ ACPI_INFO ((AE_INFO, "Loading ACPI tables")); Status = AcpiInitializeTables (NULL, 16, FALSE); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While initializing Table Manager")); return (Status); } /* Install local handlers */ Status = InstallHandlers (); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While installing handlers")); return (Status); } /* Initialize the ACPI hardware */ Status = AcpiEnableSubsystem (ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While enabling ACPICA")); return (Status); } /* Create the ACPI namespace from ACPI tables */ Status = AcpiLoadTables (); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While loading ACPI tables")); return (Status); } /* Complete the ACPI namespace object initialization */ Status = AcpiInitializeObjects (ACPI_FULL_INITIALIZATION); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "While initializing ACPICA objects")); return (Status); } return (AE_OK); }
acpi_status acpi_ex_load_table_op(struct acpi_walk_state *walk_state, union acpi_operand_object **return_desc) { acpi_status status; union acpi_operand_object **operand = &walk_state->operands[0]; acpi_native_uint table_index; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *start_node; struct acpi_namespace_node *parameter_node = NULL; union acpi_operand_object *ddb_handle; struct acpi_table_header *table; ACPI_FUNCTION_TRACE(ex_load_table_op); /* Find the ACPI table in the RSDT/XSDT */ status = acpi_tb_find_table(operand[0]->string.pointer, operand[1]->string.pointer, operand[2]->string.pointer, &table_index); if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) { return_ACPI_STATUS(status); } /* Table not found, return an Integer=0 and AE_OK */ ddb_handle = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); if (!ddb_handle) { return_ACPI_STATUS(AE_NO_MEMORY); } ddb_handle->integer.value = 0; *return_desc = ddb_handle; return_ACPI_STATUS(AE_OK); } /* Default nodes */ start_node = walk_state->scope_info->scope.node; parent_node = acpi_gbl_root_node; /* root_path (optional parameter) */ if (operand[3]->string.length > 0) { /* * Find the node referenced by the root_path_string. This is the * location within the namespace where the table will be loaded. */ status = acpi_ns_get_node(start_node, operand[3]->string.pointer, ACPI_NS_SEARCH_PARENT, &parent_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* parameter_path (optional parameter) */ if (operand[4]->string.length > 0) { if ((operand[4]->string.pointer[0] != '\\') && (operand[4]->string.pointer[0] != '^')) { /* * Path is not absolute, so it will be relative to the node * referenced by the root_path_string (or the NS root if omitted) */ start_node = parent_node; } /* Find the node referenced by the parameter_path_string */ status = acpi_ns_get_node(start_node, operand[4]->string.pointer, ACPI_NS_SEARCH_PARENT, ¶meter_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Load the table into the namespace */ status = acpi_ex_add_table(table_index, parent_node, &ddb_handle); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Parameter Data (optional) */ if (parameter_node) { /* Store the parameter data into the optional parameter object */ status = acpi_ex_store(operand[5], ACPI_CAST_PTR(union acpi_operand_object, parameter_node), walk_state); if (ACPI_FAILURE(status)) { (void)acpi_ex_unload_table(ddb_handle); return_ACPI_STATUS(status); } } status = acpi_get_table_by_index(table_index, &table); if (ACPI_SUCCESS(status)) { ACPI_INFO((AE_INFO, "Dynamic OEM Table Load - [%4.4s] OemId [%6.6s] OemTableId [%8.8s]", table->signature, table->oem_id, table->oem_table_id)); } *return_desc = ddb_handle; return_ACPI_STATUS(status); }
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); }
acpi_status acpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { /* * These Opcodes need to be removed from the namespace because they * get created even if these opcodes cannot be created due to * errors. */ if (((*op)->common.aml_opcode == AML_REGION_OP) || ((*op)->common.aml_opcode == AML_DATA_REGION_OP)) { acpi_ns_delete_children((*op)->common. node); acpi_ns_remove_node((*op)->common.node); (*op)->common.node = NULL; acpi_ps_delete_parse_tree(*op); } status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) { /* * There was something that went wrong while executing code at the * module-level. We need to skip parsing whatever caused the * error and keep going. One runtime error during the table load * should not cause the entire table to not be loaded. This is * because there could be correct AML beyond the parts that caused * the runtime error. */ ACPI_INFO(("Ignoring error and continuing table load")); return_ACPI_STATUS(AE_OK); } return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK); }
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 ((AE_INFO, "Ignoring installation of %4.4s at %8.8X%8.8X", NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); goto ReleaseAndExit; } /* Validate and verify a table before installation */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); if (ACPI_FAILURE (Status)) { goto ReleaseAndExit; } if (Reload) { /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((NewTableDesc.Signature.Ascii[0] != 0x00) && (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP (NewTableDesc.Signature.Ascii, "OEM", 3))) { ACPI_BIOS_ERROR ((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", AcpiUtValidAcpiName (NewTableDesc.Signature.Ascii) ? NewTableDesc.Signature.Ascii : "????", NewTableDesc.Signature.Integer)); Status = AE_BAD_SIGNATURE; goto ReleaseAndExit; } /* Check if table is already registered */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { /* * Check for a table match on the entire table length, * not just the header. */ if (!AcpiTbCompareTables (&NewTableDesc, i)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ Status = AE_ALREADY_EXISTS; goto ReleaseAndExit; } else { /* * 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); *TableIndex = i; return_ACPI_STATUS (AE_OK); } } } /* Add the table to the global root table list */ Status = AcpiTbGetNextTableDescriptor (&i, NULL); if (ACPI_FAILURE (Status)) { goto ReleaseAndExit; } *TableIndex = i; AcpiTbInstallTableWithOverride (i, &NewTableDesc, Override); ReleaseAndExit: /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); return_ACPI_STATUS (Status); }
ACPI_STATUS AcpiExLoadTableOp ( ACPI_WALK_STATE *WalkState, ACPI_OPERAND_OBJECT **ReturnDesc) { ACPI_STATUS Status; ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; ACPI_NAMESPACE_NODE *ParentNode; ACPI_NAMESPACE_NODE *StartNode; ACPI_NAMESPACE_NODE *ParameterNode = NULL; ACPI_OPERAND_OBJECT *DdbHandle; ACPI_TABLE_HEADER *Table; UINT32 TableIndex; ACPI_FUNCTION_TRACE (ExLoadTableOp); /* Find the ACPI table in the RSDT/XSDT */ Status = AcpiTbFindTable ( Operand[0]->String.Pointer, Operand[1]->String.Pointer, Operand[2]->String.Pointer, &TableIndex); if (ACPI_FAILURE (Status)) { if (Status != AE_NOT_FOUND) { return_ACPI_STATUS (Status); } /* Table not found, return an Integer=0 and AE_OK */ DdbHandle = AcpiUtCreateIntegerObject ((UINT64) 0); if (!DdbHandle) { return_ACPI_STATUS (AE_NO_MEMORY); } *ReturnDesc = DdbHandle; return_ACPI_STATUS (AE_OK); } /* Default nodes */ StartNode = WalkState->ScopeInfo->Scope.Node; ParentNode = AcpiGbl_RootNode; /* RootPath (optional parameter) */ if (Operand[3]->String.Length > 0) { /* * Find the node referenced by the RootPathString. This is the * location within the namespace where the table will be loaded. */ Status = AcpiNsGetNode (StartNode, Operand[3]->String.Pointer, ACPI_NS_SEARCH_PARENT, &ParentNode); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* ParameterPath (optional parameter) */ if (Operand[4]->String.Length > 0) { if ((Operand[4]->String.Pointer[0] != AML_ROOT_PREFIX) && (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX)) { /* * Path is not absolute, so it will be relative to the node * referenced by the RootPathString (or the NS root if omitted) */ StartNode = ParentNode; } /* Find the node referenced by the ParameterPathString */ Status = AcpiNsGetNode (StartNode, Operand[4]->String.Pointer, ACPI_NS_SEARCH_PARENT, &ParameterNode); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } /* Load the table into the namespace */ Status = AcpiExAddTable (TableIndex, ParentNode, &DdbHandle); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Parameter Data (optional) */ if (ParameterNode) { /* Store the parameter data into the optional parameter object */ Status = AcpiExStore (Operand[5], ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, ParameterNode), WalkState); if (ACPI_FAILURE (Status)) { (void) AcpiExUnloadTable (DdbHandle); AcpiUtRemoveReference (DdbHandle); return_ACPI_STATUS (Status); } } Status = AcpiGetTableByIndex (TableIndex, &Table); if (ACPI_SUCCESS (Status)) { ACPI_INFO (("Dynamic OEM Table Load:")); AcpiTbPrintTableHeader (0, Table); } /* Invoke table handler if present */ if (AcpiGbl_TableHandler) { (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_LOAD, Table, AcpiGbl_TableHandlerContext); } *ReturnDesc = DdbHandle; return_ACPI_STATUS (Status); }
void AcpiTbOverrideTable ( ACPI_TABLE_DESC *OldTableDesc) { ACPI_STATUS Status; char *OverrideType; ACPI_TABLE_DESC NewTableDesc; ACPI_TABLE_HEADER *Table; ACPI_PHYSICAL_ADDRESS Address; UINT32 Length; /* (1) Attempt logical override (returns a logical address) */ Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); if (ACPI_SUCCESS (Status) && Table) { AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); OverrideType = "Logical"; goto FinishOverride; } /* (2) Attempt physical override (returns a physical address) */ Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, &Address, &Length); if (ACPI_SUCCESS (Status) && Address && Length) { AcpiTbAcquireTempTable (&NewTableDesc, Address, ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); OverrideType = "Physical"; goto FinishOverride; } return; /* There was no override */ FinishOverride: /* Validate and verify a table before overriding */ Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL); if (ACPI_FAILURE (Status)) { return; } ACPI_INFO ((AE_INFO, "%4.4s 0x%8.8X%8.8X" " %s table override, new table: 0x%8.8X%8.8X", OldTableDesc->Signature.Ascii, ACPI_FORMAT_UINT64 (OldTableDesc->Address), OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); /* We can now uninstall the original table */ AcpiTbUninstallTable (OldTableDesc); /* * Replace the original table descriptor and keep its state as * "VALIDATED". */ AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, NewTableDesc.Flags, NewTableDesc.Pointer); AcpiTbValidateTempTable (OldTableDesc); /* Release the temporary table descriptor */ AcpiTbReleaseTempTable (&NewTableDesc); }
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 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; }
struct acpi_table_header *acpi_tb_table_override(struct acpi_table_header *table_header, struct acpi_table_desc *table_desc) { acpi_status status; struct acpi_table_header *new_table = NULL; acpi_physical_address new_address = 0; u32 new_table_length = 0; u8 new_flags; char *override_type; /* (1) Attempt logical override (returns a logical address) */ status = acpi_os_table_override(table_header, &new_table); if (ACPI_SUCCESS(status) && new_table) { new_address = ACPI_PTR_TO_PHYSADDR(new_table); new_table_length = new_table->length; new_flags = ACPI_TABLE_ORIGIN_OVERRIDE; override_type = "Logical"; goto finish_override; } /* (2) Attempt physical override (returns a physical address) */ status = acpi_os_physical_table_override(table_header, &new_address, &new_table_length); if (ACPI_SUCCESS(status) && new_address && new_table_length) { /* Map the entire new table */ new_table = acpi_os_map_memory(new_address, new_table_length); if (!new_table) { ACPI_EXCEPTION((AE_INFO, AE_NO_MEMORY, "%4.4s %p Attempted physical table override failed", table_header->signature, ACPI_PHYSADDR_TO_PTR(table_desc->address))); return (NULL); } override_type = "Physical"; new_flags = ACPI_TABLE_ORIGIN_MAPPED; goto finish_override; } return (NULL); /* There was no override */ finish_override: ACPI_INFO((AE_INFO, "%4.4s %p %s table override, new table: %p", table_header->signature, ACPI_PHYSADDR_TO_PTR(table_desc->address), override_type, new_table)); /* We can now unmap/delete the original table (if fully mapped) */ acpi_tb_delete_table(table_desc); /* Setup descriptor for the new table */ table_desc->address = new_address; table_desc->pointer = new_table; table_desc->length = new_table_length; table_desc->flags = new_flags; return (new_table); }
ACPI_STATUS AcpiEvInitializeGpeBlock ( ACPI_GPE_XRUPT_INFO *GpeXruptInfo, ACPI_GPE_BLOCK_INFO *GpeBlock, void *Ignored) { ACPI_STATUS Status; ACPI_GPE_EVENT_INFO *GpeEventInfo; UINT32 GpeEnabledCount; UINT32 GpeIndex; UINT32 i; UINT32 j; ACPI_FUNCTION_TRACE (EvInitializeGpeBlock); /* * Ignore a null GPE block (e.g., if no GPE block 1 exists), and * any GPE blocks that have been initialized already. */ if (!GpeBlock || GpeBlock->Initialized) { return_ACPI_STATUS (AE_OK); } /* * Enable all GPEs that have a corresponding method and have the * ACPI_GPE_CAN_WAKE flag unset. Any other GPEs within this block * must be enabled via the acpi_enable_gpe() interface. */ GpeEnabledCount = 0; for (i = 0; i < GpeBlock->RegisterCount; i++) { for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Get the info block for this particular GPE */ GpeIndex = (i * ACPI_GPE_REGISTER_WIDTH) + j; GpeEventInfo = &GpeBlock->EventInfo[GpeIndex]; /* * Ignore GPEs that have no corresponding _Lxx/_Exx method * and GPEs that are used to wake the system */ if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_NONE) || (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_HANDLER) || (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == ACPI_GPE_DISPATCH_RAW_HANDLER) || (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) { continue; } Status = AcpiEvAddGpeReference (GpeEventInfo); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not enable GPE 0x%02X", GpeIndex + GpeBlock->BlockBaseNumber)); continue; } GpeEnabledCount++; } } if (GpeEnabledCount) { ACPI_INFO (( "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount, (UINT32) GpeBlock->BlockBaseNumber, (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)))); } GpeBlock->Initialized = TRUE; return_ACPI_STATUS (AE_OK); }
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); }
void AcpiDbDisplayTableInfo ( char *TableArg) { UINT32 i; ACPI_TABLE_DESC *TableDesc; ACPI_STATUS Status; /* Header */ AcpiOsPrintf ("Idx ID Status Type Sig Address Len Header\n"); /* Walk the entire root table list */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) { TableDesc = &AcpiGbl_RootTableList.Tables[i]; /* Index and Table ID */ AcpiOsPrintf ("%3u %.2u ", i, TableDesc->OwnerId); /* Decode the table flags */ if (!(TableDesc->Flags & ACPI_TABLE_IS_LOADED)) { AcpiOsPrintf ("NotLoaded "); } else { AcpiOsPrintf (" Loaded "); } switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) { case ACPI_TABLE_ORIGIN_UNKNOWN: AcpiOsPrintf ("Unknown "); break; case ACPI_TABLE_ORIGIN_MAPPED: AcpiOsPrintf ("Mapped "); break; case ACPI_TABLE_ORIGIN_ALLOCATED: AcpiOsPrintf ("Allocated "); break; case ACPI_TABLE_ORIGIN_OVERRIDE: AcpiOsPrintf ("Override "); break; default: AcpiOsPrintf ("INVALID "); break; } /* Make sure that the table is mapped */ Status = AcpiTbVerifyTable (TableDesc); if (ACPI_FAILURE (Status)) { return; } /* Dump the table header */ if (TableDesc->Pointer) { AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); } else { /* If the pointer is null, the table has been unloaded */ ACPI_INFO ((AE_INFO, "%4.4s - Table has been unloaded", TableDesc->Signature.Ascii)); } } }
/******************************************************************************* * * FUNCTION: acpi_tb_load_namespace * * PARAMETERS: None * * RETURN: Status * * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in * the RSDT/XSDT. * ******************************************************************************/ static acpi_status acpi_tb_load_namespace(void) { acpi_status status; u32 i; struct acpi_table_header *new_dsdt; ACPI_FUNCTION_TRACE(tb_load_namespace); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* * Load the namespace. The DSDT is required, but any SSDT and * PSDT tables are optional. Verify the DSDT. */ if (!acpi_gbl_root_table_list.current_table_count || !ACPI_COMPARE_NAME(& (acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT].signature), ACPI_SIG_DSDT) || ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list. tables[ACPI_TABLE_INDEX_DSDT]))) { status = AE_NO_ACPI_TABLES; goto unlock_and_exit; } /* * 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 acpi_tb_validate_table. */ acpi_gbl_DSDT = acpi_gbl_root_table_list.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 (acpi_gbl_copy_dsdt_locally) { new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT); if (new_dsdt) { acpi_gbl_DSDT = new_dsdt; } } /* * Save the original DSDT header for detection of table corruption * and/or replacement of the DSDT from outside the OS. */ ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT, sizeof(struct acpi_table_header)); (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); /* Load and parse tables */ status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { if (!acpi_gbl_root_table_list.tables[i].address || (!ACPI_COMPARE_NAME (&(acpi_gbl_root_table_list.tables[i].signature), ACPI_SIG_SSDT) && !ACPI_COMPARE_NAME(& (acpi_gbl_root_table_list.tables[i]. signature), ACPI_SIG_PSDT)) || ACPI_FAILURE(acpi_tb_validate_table (&acpi_gbl_root_table_list.tables[i]))) { continue; } /* Ignore errors while loading tables, get as many as possible */ (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); (void)acpi_ns_load_table(i, acpi_gbl_root_node); (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); } ACPI_INFO((AE_INFO, "All ACPI Tables successfully acquired")); unlock_and_exit: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); }