ACPI_STATUS AcpiOsCreateSemaphore ( UINT32 MaxUnits, UINT32 InitialUnits, ACPI_SEMAPHORE *OutHandle) { void *Mutex; UINT32 i; ACPI_FUNCTION_NAME (OsCreateSemaphore); if (MaxUnits == ACPI_UINT32_MAX) { MaxUnits = 255; } if (InitialUnits == ACPI_UINT32_MAX) { InitialUnits = MaxUnits; } if (InitialUnits > MaxUnits) { return (AE_BAD_PARAMETER); } /* Find an empty slot */ for (i = 0; i < ACPI_OS_MAX_SEMAPHORES; i++) { if (!AcpiGbl_Semaphores[i].OsHandle) { break; } } if (i >= ACPI_OS_MAX_SEMAPHORES) { ACPI_EXCEPTION ((AE_INFO, AE_LIMIT, "Reached max semaphores (%u), could not create", ACPI_OS_MAX_SEMAPHORES)); return (AE_LIMIT); } /* Create an OS semaphore */ Mutex = CreateSemaphore (NULL, InitialUnits, MaxUnits, NULL); if (!Mutex) { ACPI_ERROR ((AE_INFO, "Could not create semaphore")); return (AE_NO_MEMORY); } AcpiGbl_Semaphores[i].MaxUnits = (UINT16) MaxUnits; AcpiGbl_Semaphores[i].CurrentUnits = (UINT16) InitialUnits; AcpiGbl_Semaphores[i].OsHandle = Mutex; ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Handle=%u, Max=%u, Current=%u, OsHandle=%p\n", i, MaxUnits, InitialUnits, Mutex)); *OutHandle = (void *) i; return (AE_OK); }
acpi_status acpi_ns_check_package(struct acpi_evaluate_info *info, union acpi_operand_object **return_object_ptr) { union acpi_operand_object *return_object = *return_object_ptr; const union acpi_predefined_info *package; union acpi_operand_object **elements; acpi_status status = AE_OK; u32 expected_count; u32 count; u32 i; ACPI_FUNCTION_NAME(ns_check_package); /* The package info for this name is in the next table entry */ package = info->predefined + 1; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s Validating return Package of Type %X, Count %X\n", info->full_pathname, package->ret_info.type, return_object->package.count)); /* * For variable-length Packages, we can safely remove all embedded * and trailing NULL package elements */ acpi_ns_remove_null_elements(info, package->ret_info.type, return_object); /* Extract package count and elements array */ elements = return_object->package.elements; count = return_object->package.count; /* * Most packages must have at least one element. The only exception * is the variable-length package (ACPI_PTYPE1_VAR). */ if (!count) { if (package->ret_info.type == ACPI_PTYPE1_VAR) { return (AE_OK); } ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return Package has no elements (empty)")); return (AE_AML_OPERAND_VALUE); } /* * Decode the type of the expected package contents * * PTYPE1 packages contain no subpackages * PTYPE2 packages contain subpackages */ switch (package->ret_info.type) { case ACPI_PTYPE_CUSTOM: status = acpi_ns_custom_package(info, elements, count); break; case ACPI_PTYPE1_FIXED: /* * The package count is fixed and there are no subpackages * * If package is too small, exit. * If package is larger than expected, issue warning but continue */ expected_count = package->ret_info.count1 + package->ret_info.count2; if (count < expected_count) { goto package_too_small; } else if (count > expected_count) { ACPI_DEBUG_PRINT((ACPI_DB_REPAIR, "%s: Return Package is larger than needed - " "found %u, expected %u\n", info->full_pathname, count, expected_count)); } /* Validate all elements of the returned package */ status = acpi_ns_check_package_elements(info, elements, package->ret_info. object_type1, package->ret_info. count1, package->ret_info. object_type2, package->ret_info. count2, 0); break; case ACPI_PTYPE1_VAR: /* * The package count is variable, there are no subpackages, and all * elements must be of the same type */ for (i = 0; i < count; i++) { status = acpi_ns_check_object_type(info, elements, package->ret_info. object_type1, i); if (ACPI_FAILURE(status)) { return (status); } elements++; } break; case ACPI_PTYPE1_OPTION: /* * The package count is variable, there are no subpackages. There are * a fixed number of required elements, and a variable number of * optional elements. * * Check if package is at least as large as the minimum required */ expected_count = package->ret_info3.count; if (count < expected_count) { goto package_too_small; } /* Variable number of sub-objects */ for (i = 0; i < count; i++) { if (i < package->ret_info3.count) { /* These are the required package elements (0, 1, or 2) */ status = acpi_ns_check_object_type(info, elements, package-> ret_info3. object_type[i], i); if (ACPI_FAILURE(status)) { return (status); } } else { /* These are the optional package elements */ status = acpi_ns_check_object_type(info, elements, package-> ret_info3. tail_object_type, i); if (ACPI_FAILURE(status)) { return (status); } } elements++; } break; case ACPI_PTYPE2_REV_FIXED: /* First element is the (Integer) revision */ status = acpi_ns_check_object_type(info, elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { return (status); } elements++; count--; /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); break; case ACPI_PTYPE2_PKG_COUNT: /* First element is the (Integer) count of subpackages to follow */ status = acpi_ns_check_object_type(info, elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { return (status); } /* * Count cannot be larger than the parent package length, but allow it * to be smaller. The >= accounts for the Integer above. */ expected_count = (u32)(*elements)->integer.value; if (expected_count >= count) { goto package_too_small; } count = expected_count; elements++; /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); break; case ACPI_PTYPE2: case ACPI_PTYPE2_FIXED: case ACPI_PTYPE2_MIN: case ACPI_PTYPE2_COUNT: case ACPI_PTYPE2_FIX_VAR: /* * These types all return a single Package that consists of a * variable number of subpackages. * * First, ensure that the first element is a subpackage. If not, * the BIOS may have incorrectly returned the object as a single * package instead of a Package of Packages (a common error if * there is only one entry). We may be able to repair this by * wrapping the returned Package with a new outer Package. */ if (*elements && ((*elements)->common.type != ACPI_TYPE_PACKAGE)) { /* Create the new outer package and populate it */ status = acpi_ns_wrap_with_package(info, return_object, return_object_ptr); if (ACPI_FAILURE(status)) { return (status); } /* Update locals to point to the new package (of 1 element) */ return_object = *return_object_ptr; elements = return_object->package.elements; count = 1; } /* Examine the subpackages */ status = acpi_ns_check_package_list(info, package, elements, count); break; case ACPI_PTYPE2_VAR_VAR: /* * Returns a variable list of packages, each with a variable list * of objects. */ break; case ACPI_PTYPE2_UUID_PAIR: /* The package must contain pairs of (UUID + type) */ if (count & 1) { expected_count = count + 1; goto package_too_small; } while (count > 0) { status = acpi_ns_check_object_type(info, elements, package->ret_info. object_type1, 0); if (ACPI_FAILURE(status)) { return (status); } /* Validate length of the UUID buffer */ if ((*elements)->buffer.length != 16) { ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Invalid length for UUID Buffer")); return (AE_AML_OPERAND_VALUE); } status = acpi_ns_check_object_type(info, elements + 1, package->ret_info. object_type2, 0); if (ACPI_FAILURE(status)) { return (status); } elements += 2; count -= 2; } break; default: /* Should not get here if predefined info table is correct */ ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Invalid internal return type in table entry: %X", package->ret_info.type)); return (AE_AML_INTERNAL); } return (status); package_too_small: /* Error exit for the case with an incorrect package count */ ACPI_WARN_PREDEFINED((AE_INFO, info->full_pathname, info->node_flags, "Return Package is too small - found %u elements, expected %u", count, expected_count)); return (AE_AML_OPERAND_VALUE); }
static ACPI_STATUS OptSearchToRoot ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE *CurrentNode, ACPI_NAMESPACE_NODE *TargetNode, ACPI_BUFFER *TargetPath, char **NewPath) { ACPI_NAMESPACE_NODE *Node; ACPI_GENERIC_STATE ScopeInfo; ACPI_STATUS Status; char *Path; ACPI_FUNCTION_NAME (OptSearchToRoot); /* * Check if search-to-root can be utilized. Use the last NameSeg of * the NamePath and 1) See if can be found and 2) If found, make * sure that it is the same node that we want. If there is another * name in the search path before the one we want, the nodes will * not match, and we cannot use this optimization. */ Path = &(((char *) TargetPath->Pointer)[TargetPath->Length - ACPI_NAME_SIZE]), ScopeInfo.Scope.Node = CurrentNode; /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */ Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { return (Status); } /* * We found the name, but we must check to make sure that the node * matches. Otherwise, there is another identical name in the search * path that precludes the use of this optimization. */ if (Node != TargetNode) { /* * This means that another object with the same name was found first, * and we cannot use this optimization. */ return (AE_NOT_FOUND); } /* Found the node, we can use this optimization */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAMESEG: %-24s", Path)); /* We must allocate a new string for the name (TargetPath gets deleted) */ *NewPath = ACPI_ALLOCATE_ZEROED (ACPI_NAME_SIZE + 1); ACPI_STRCPY (*NewPath, Path); if (ACPI_STRNCMP (*NewPath, "_T_", 3)) { AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op, *NewPath); } return (AE_OK); }
static ACPI_STATUS LdNamespace1Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_OBJECT_TYPE ObjectType; ACPI_OBJECT_TYPE ActualObjectType = ACPI_TYPE_ANY; char *Path; UINT32 Flags = ACPI_NS_NO_UPSEARCH; ACPI_PARSE_OBJECT *Arg; UINT32 i; BOOLEAN ForceNewScope = FALSE; ACPI_FUNCTION_NAME (LdNamespace1Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); /* * We are only interested in opcodes that have an associated name * (or multiple names) */ switch (Op->Asl.AmlOpcode) { case AML_BANK_FIELD_OP: case AML_INDEX_FIELD_OP: case AML_FIELD_OP: Status = LdLoadFieldElements (Op, WalkState); return (Status); default: /* All other opcodes go below */ break; } /* Check if this object has already been installed in the namespace */ if (Op->Asl.Node) { return (AE_OK); } Path = Op->Asl.Namepath; if (!Path) { return (AE_OK); } /* Map the raw opcode into an internal object type */ switch (Op->Asl.ParseOpcode) { case PARSEOP_NAME: Arg = Op->Asl.Child; /* Get the NameSeg/NameString node */ Arg = Arg->Asl.Next; /* First peer is the object to be associated with the name */ /* * If this name refers to a ResourceTemplate, we will need to open * a new scope so that the resource subfield names can be entered into * the namespace underneath this name */ if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } /* Get the data type associated with the named object, not the name itself */ /* Log2 loop to convert from Btype (binary) to Etype (encoded) */ ObjectType = 1; for (i = 1; i < Arg->Asl.AcpiBtype; i *= 2) { ObjectType++; } break; case PARSEOP_EXTERNAL: /* * "External" simply enters a name and type into the namespace. * We must be careful to not open a new scope, however, no matter * what type the external name refers to (e.g., a method) * * first child is name, next child is ObjectType */ ActualObjectType = (UINT8) Op->Asl.Child->Asl.Next->Asl.Value.Integer; ObjectType = ACPI_TYPE_ANY; /* * We will mark every new node along the path as "External". This * allows some or all of the nodes to be created later in the ASL * code. Handles cases like this: * * External (\_SB_.PCI0.ABCD, IntObj) * Scope (_SB_) * { * Device (PCI0) * { * } * } * Method (X) * { * Store (\_SB_.PCI0.ABCD, Local0) * } */ Flags |= ACPI_NS_EXTERNAL; break; case PARSEOP_DEFAULT_ARG: if (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC) { Status = LdLoadResourceElements (Op, WalkState); return_ACPI_STATUS (Status); } ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; case PARSEOP_SCOPE: /* * The name referenced by Scope(Name) must already exist at this point. * In other words, forward references for Scope() are not supported. * The only real reason for this is that the MS interpreter cannot * handle this case. Perhaps someday this case can go away. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, WalkState, &(Node)); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* The name was not found, go ahead and create it */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_LOCAL_SCOPE, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &(Node)); /* * However, this is an error -- primarily because the MS * interpreter can't handle a forward reference from the * Scope() operator. */ AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); AslError (ASL_ERROR, ASL_MSG_SCOPE_FWD_REF, Op, Op->Asl.ExternalName); goto FinishNode; } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } /* We found a node with this name, now check the type */ switch (Node->Type) { case ACPI_TYPE_LOCAL_SCOPE: case ACPI_TYPE_DEVICE: case ACPI_TYPE_POWER: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_THERMAL: /* These are acceptable types - they all open a new scope */ break; case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * These types we will allow, but we will change the type. * This enables some existing code of the form: * * Name (DEB, 0) * Scope (DEB) { ... } * * Which is used to workaround the fact that the MS interpreter * does not allow Scope() forward references. */ sprintf (MsgBuffer, "%s [%s], changing type to [Scope]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_REMARK, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* Switch the type to scope, open the new scope */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; default: /* All other types are an error */ sprintf (MsgBuffer, "%s [%s]", Op->Asl.ExternalName, AcpiUtGetTypeName (Node->Type)); AslError (ASL_ERROR, ASL_MSG_SCOPE_TYPE, Op, MsgBuffer); /* * However, switch the type to be an actual scope so * that compilation can continue without generating a whole * cascade of additional errors. Open the new scope. */ Node->Type = ACPI_TYPE_LOCAL_SCOPE; Status = AcpiDsScopeStackPush (Node, ACPI_TYPE_LOCAL_SCOPE, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } break; } Status = AE_OK; goto FinishNode; default: ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); break; } ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Loading name: %s, (%s)\n", Op->Asl.ExternalName, AcpiUtGetTypeName (ObjectType))); /* The name must not already exist */ Flags |= ACPI_NS_ERROR_IF_FOUND; /* * Enter the named type into the internal namespace. We enter the name * as we go downward in the parse tree. Any necessary subobjects that * involve arguments to the opcode must be created as we go back up the * parse tree later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS1, Flags, WalkState, &Node); if (ACPI_FAILURE (Status)) { if (Status == AE_ALREADY_EXISTS) { /* The name already exists in this scope */ if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) { /* Allow multiple references to the same scope */ Node->Type = (UINT8) ObjectType; Status = AE_OK; } else if ((Node->Flags & ANOBJ_IS_EXTERNAL) && (Op->Asl.ParseOpcode != PARSEOP_EXTERNAL)) { /* * Allow one create on an object or segment that was * previously declared External */ Node->Flags &= ~ANOBJ_IS_EXTERNAL; Node->Type = (UINT8) ObjectType; /* Just retyped a node, probably will need to open a scope */ if (AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } Status = AE_OK; } else { /* Valid error, object already exists */ AslError (ASL_ERROR, ASL_MSG_NAME_EXISTS, Op, Op->Asl.ExternalName); return_ACPI_STATUS (AE_OK); } } else { AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return_ACPI_STATUS (Status); } } if (ForceNewScope) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } FinishNode: /* * Point the parse node to the new namespace node, and point * the Node back to the original Parse node */ Op->Asl.Node = Node; Node->Op = Op; /* Set the actual data type if appropriate (EXTERNAL term only) */ if (ActualObjectType != ACPI_TYPE_ANY) { Node->Type = (UINT8) ActualObjectType; Node->Value = ASL_EXTERNAL_METHOD; } if (Op->Asl.ParseOpcode == PARSEOP_METHOD) { /* * Get the method argument count from "Extra" and save * it in the namespace node */ Node->Value = (UINT32) Op->Asl.Extra; } return_ACPI_STATUS (Status); }
u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) { acpi_status status; struct acpi_gpe_block_info *gpe_block; struct acpi_gpe_register_info *gpe_register_info; u32 int_status = ACPI_INTERRUPT_NOT_HANDLED; u8 enabled_status_byte; u32 status_reg; u32 enable_reg; acpi_cpu_flags flags; u32 i; u32 j; ACPI_FUNCTION_NAME(ev_gpe_detect); /* Check for the case where there are no GPEs */ if (!gpe_xrupt_list) { return (int_status); } /* * We need to obtain the GPE lock for both the data structs and registers * Note: Not necessary to obtain the hardware lock, since the GPE * registers are owned by the gpe_lock. */ flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); /* Examine all GPE blocks attached to this interrupt level */ gpe_block = gpe_xrupt_list->gpe_block_list_head; while (gpe_block) { /* * Read all of the 8-bit GPE status and enable registers in this GPE * block, saving all of them. Find all currently active GP events. */ for (i = 0; i < gpe_block->register_count; i++) { /* Get the next status/enable pair */ gpe_register_info = &gpe_block->register_info[i]; /* * Optimization: If there are no GPEs enabled within this * register, we can safely ignore the entire register. */ if (!(gpe_register_info->enable_for_run | gpe_register_info->enable_for_wake)) { ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, "Ignore disabled registers for GPE%02X-GPE%02X: " "RunEnable=%02X, WakeEnable=%02X\n", gpe_register_info-> base_gpe_number, gpe_register_info-> base_gpe_number + (ACPI_GPE_REGISTER_WIDTH - 1), gpe_register_info-> enable_for_run, gpe_register_info-> enable_for_wake)); continue; } /* Read the Status Register */ status = acpi_hw_read(&status_reg, &gpe_register_info->status_address); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } /* Read the Enable Register */ status = acpi_hw_read(&enable_reg, &gpe_register_info->enable_address); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } ACPI_DEBUG_PRINT((ACPI_DB_INTERRUPTS, "Read registers for GPE%02X-GPE%02X: Status=%02X, Enable=%02X, " "RunEnable=%02X, WakeEnable=%02X\n", gpe_register_info->base_gpe_number, gpe_register_info->base_gpe_number + (ACPI_GPE_REGISTER_WIDTH - 1), status_reg, enable_reg, gpe_register_info->enable_for_run, gpe_register_info->enable_for_wake)); /* Check if there is anything active at all in this register */ enabled_status_byte = (u8) (status_reg & enable_reg); if (!enabled_status_byte) { /* No active GPEs in this register, move on */ continue; } /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Examine one GPE bit */ if (enabled_status_byte & (1 << j)) { /* * Found an active GPE. Dispatch the event to a handler * or method. */ int_status |= acpi_ev_gpe_dispatch(gpe_block-> node, &gpe_block-> event_info[((acpi_size) i * ACPI_GPE_REGISTER_WIDTH) + j], j + gpe_register_info->base_gpe_number); } } } gpe_block = gpe_block->next; } unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return (int_status); }
ACPI_STATUS AcpiUtAcquireMutex ( ACPI_MUTEX_HANDLE MutexId) { ACPI_STATUS Status; UINT32 i; UINT32 ThisThreadId; ACPI_FUNCTION_NAME ("UtAcquireMutex"); if (MutexId > MAX_MTX) { return (AE_BAD_PARAMETER); } ThisThreadId = AcpiOsGetThreadId (); /* * Deadlock prevention. Check if this thread owns any mutexes of value * greater than or equal to this one. If so, the thread has violated * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = MutexId; i < MAX_MTX; i++) { if (AcpiGbl_AcpiMutexInfo[i].OwnerId == ThisThreadId) { if (i == MutexId) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] already acquired by this thread [%X]\n", AcpiUtGetMutexName (MutexId), ThisThreadId)); return (AE_ALREADY_ACQUIRED); } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", ThisThreadId, AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); return (AE_ACQUIRE_DEADLOCK); } } ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X attempting to acquire Mutex [%s]\n", ThisThreadId, AcpiUtGetMutexName (MutexId))); Status = AcpiOsWaitSemaphore (AcpiGbl_AcpiMutexInfo[MutexId].Mutex, 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", ThisThreadId, AcpiUtGetMutexName (MutexId))); AcpiGbl_AcpiMutexInfo[MutexId].UseCount++; AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ThisThreadId; } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", ThisThreadId, AcpiUtGetMutexName (MutexId), AcpiFormatException (Status))); } return (Status); }
static acpi_status acpi_ev_install_handler(acpi_handle obj_handle, u32 level, void *context, void **return_value) { union acpi_operand_object *handler_obj; union acpi_operand_object *next_handler_obj; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; acpi_status status; ACPI_FUNCTION_NAME(ev_install_handler); handler_obj = (union acpi_operand_object *)context; /* Parameter validation */ if (!handler_obj) { return (AE_OK); } /* Convert and validate the device handle */ node = acpi_ns_validate_handle(obj_handle); if (!node) { return (AE_BAD_PARAMETER); } /* * We only care about regions and objects that are allowed to have * address space handlers */ if ((node->type != ACPI_TYPE_DEVICE) && (node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { return (AE_OK); } /* Check for an existing internal object */ obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { /* No object, just exit */ return (AE_OK); } /* Devices are handled different than regions */ if (obj_desc->common.type == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ next_handler_obj = obj_desc->device.handler; while (next_handler_obj) { /* Found a handler, is it for the same address space? */ if (next_handler_obj->address_space.space_id == handler_obj->address_space.space_id) { ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) " "handler %p\n", acpi_ut_get_region_name (handler_obj->address_space. space_id), obj_desc, next_handler_obj, handler_obj)); /* * Since the object we found it on was a device, then it * means that someone has already installed a handler for * the branch of the namespace from this device on. Just * bail out telling the walk routine to not traverse this * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } /* Walk the linked list of handlers attached to this device */ next_handler_obj = next_handler_obj->address_space.next; } /* * As long as the device didn't have a handler for this space we * don't care about it. We just ignore it and proceed. */ return (AE_OK); } /* Object is a Region */ if (obj_desc->region.space_id != handler_obj->address_space.space_id) { /* This region is for a different address space, just ignore it */ return (AE_OK); } /* * Now we have a region and it is for the handler's address space type. * * First disconnect region for any previous handler (if any) */ acpi_ev_detach_region(obj_desc, FALSE); /* Connect the region to the new handler */ status = acpi_ev_attach_region(handler_obj, obj_desc, FALSE); return (status); }
static acpi_status acpi_ns_init_one_object(acpi_handle obj_handle, u32 level, void *context, void **return_value) { acpi_object_type type; acpi_status status = AE_OK; struct acpi_init_walk_info *info = (struct acpi_init_walk_info *)context; struct acpi_namespace_node *node = (struct acpi_namespace_node *)obj_handle; union acpi_operand_object *obj_desc; ACPI_FUNCTION_NAME(ns_init_one_object); info->object_count++; /* And even then, we are only interested in a few object types */ type = acpi_ns_get_type(obj_handle); obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (type) { case ACPI_TYPE_REGION: info->op_region_count++; break; case ACPI_TYPE_BUFFER_FIELD: info->field_count++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_count++; break; case ACPI_TYPE_BUFFER: info->buffer_count++; break; case ACPI_TYPE_PACKAGE: info->package_count++; break; default: /* No init required, just exit now */ return (AE_OK); } /* If the object is already initialized, nothing else to do */ if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* Must lock the interpreter before executing AML code */ acpi_ex_enter_interpreter(); /* * Each of these types can contain executable AML code within the * declaration. */ switch (type) { case ACPI_TYPE_REGION: info->op_region_init++; status = acpi_ds_get_region_arguments(obj_desc); break; case ACPI_TYPE_BUFFER_FIELD: info->field_init++; status = acpi_ds_get_buffer_field_arguments(obj_desc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: info->field_init++; status = acpi_ds_get_bank_field_arguments(obj_desc); break; case ACPI_TYPE_BUFFER: info->buffer_init++; status = acpi_ds_get_buffer_arguments(obj_desc); break; case ACPI_TYPE_PACKAGE: info->package_init++; status = acpi_ds_get_package_arguments(obj_desc); break; default: /* No other types can get here */ break; } if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "Could not execute arguments for [%4.4s] (%s)", acpi_ut_get_node_name(node), acpi_ut_get_type_name(type))); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ acpi_ex_exit_interpreter(); return (AE_OK); }
void __init acpi_table_print_srat_entry(struct acpi_subtable_header * header) { ACPI_FUNCTION_NAME("acpi_table_print_srat_entry"); if (!header) return; switch (header->type) { case ACPI_SRAT_TYPE_CPU_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_cpu_affinity *p = container_of(header, struct acpi_srat_cpu_affinity, header); u32 proximity_domain = p->proximity_domain_lo; if (srat_rev >= 2) { proximity_domain |= p->proximity_domain_hi[0] << 8; proximity_domain |= p->proximity_domain_hi[1] << 16; proximity_domain |= p->proximity_domain_hi[2] << 24; } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (id[0x%02x] eid[0x%02x]) in proximity domain %d %s\n", p->apic_id, p->local_sapic_eid, proximity_domain, p->flags & ACPI_SRAT_CPU_ENABLED ? "enabled" : "disabled")); } #endif /* ACPI_DEBUG_OUTPUT */ break; case ACPI_SRAT_TYPE_MEMORY_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_mem_affinity *p = container_of(header, struct acpi_srat_mem_affinity, header); u32 proximity_domain = p->proximity_domain; if (srat_rev < 2) proximity_domain &= 0xff; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Memory (%#"PRIx64 " length %#"PRIx64")" " in proximity domain %d %s%s\n", p->base_address, p->length, proximity_domain, p->flags & ACPI_SRAT_MEM_ENABLED ? "enabled" : "disabled", p->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE ? " hot-pluggable" : "")); } #endif /* ACPI_DEBUG_OUTPUT */ break; case ACPI_SRAT_TYPE_X2APIC_CPU_AFFINITY: #ifdef ACPI_DEBUG_OUTPUT { struct acpi_srat_x2apic_cpu_affinity *p = (struct acpi_srat_x2apic_cpu_affinity *)header; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SRAT Processor (x2apicid[0x%08x]) in" " proximity domain %d %s\n", p->apic_id, p->proximity_domain, (p->flags & ACPI_SRAT_CPU_ENABLED) ? "enabled" : "disabled")); } #endif /* ACPI_DEBUG_OUTPUT */ break; default: printk(KERN_WARNING PREFIX "Found unsupported SRAT entry (type = %#x)\n", header->type); break; } }
ACPI_STATUS AcpiOsActualCreateSemaphore ( UINT32 MaxUnits, UINT32 InitialUnits, ACPI_HANDLE *OutHandle) { #ifdef _MULTI_THREADED void *Mutex; UINT32 i; ACPI_FUNCTION_NAME (OsCreateSemaphore); #endif if (MaxUnits == ACPI_UINT32_MAX) { MaxUnits = 255; } if (InitialUnits == ACPI_UINT32_MAX) { InitialUnits = MaxUnits; } if (InitialUnits > MaxUnits) { return AE_BAD_PARAMETER; } #ifdef _MULTI_THREADED /* Find an empty slot */ for (i = 0; i < NUM_SEMAPHORES; i++) { if (!AcpiGbl_Semaphores[i].OsHandle) { break; } } if (i >= NUM_SEMAPHORES) { return AE_LIMIT; } /* Create an OS semaphore */ Mutex = CreateSemaphore (NULL, InitialUnits, MaxUnits, NULL); if (!Mutex) { ACPI_ERROR ((AE_INFO, "Could not create semaphore")); return AE_NO_MEMORY; } AcpiGbl_Semaphores[i].MaxUnits = (UINT16) MaxUnits; AcpiGbl_Semaphores[i].CurrentUnits = (UINT16) InitialUnits; AcpiGbl_Semaphores[i].OsHandle = Mutex; ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Handle=%d, Max=%d, Current=%d, OsHandle=%p\n", i, MaxUnits, InitialUnits, Mutex)); *OutHandle = (void *) i; #endif return AE_OK; }
static void AcpiUtUpdateRefCount ( ACPI_OPERAND_OBJECT *Object, UINT32 Action) { UINT16 Count; UINT16 NewCount; ACPI_FUNCTION_NAME (UtUpdateRefCount); if (!Object) { return; } Count = Object->Common.ReferenceCount; NewCount = Count; /* * Perform the reference count action (increment, decrement, force delete) */ switch (Action) { case REF_INCREMENT: NewCount++; Object->Common.ReferenceCount = NewCount; ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Incremented]\n", Object, NewCount)); break; case REF_DECREMENT: if (Count < 1) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, can't decrement! (Set to 0)\n", Object, NewCount)); NewCount = 0; } else { NewCount--; ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, [Decremented]\n", Object, NewCount)); } if (Object->Common.Type == ACPI_TYPE_METHOD) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount)); } Object->Common.ReferenceCount = NewCount; if (NewCount == 0) { AcpiUtDeleteInternalObj (Object); } break; case REF_FORCE_DELETE: ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count)); NewCount = 0; Object->Common.ReferenceCount = NewCount; AcpiUtDeleteInternalObj (Object); break; default: ACPI_ERROR ((AE_INFO, "Unknown action (0x%X)", Action)); break; } /* * Sanity check the reference count, for debug purposes only. * (A deleted object will have a huge reference count) */ if (Count > ACPI_MAX_REFERENCE_COUNT) { ACPI_WARNING ((AE_INFO, "Large Reference Count (0x%X) in object %p", Count, Object)); } }
ACPI_STATUS AcpiEvQueueNotifyRequest ( ACPI_NAMESPACE_NODE *Node, UINT32 NotifyValue) { ACPI_OPERAND_OBJECT *ObjDesc; ACPI_OPERAND_OBJECT *HandlerListHead = NULL; ACPI_GENERIC_STATE *Info; UINT8 HandlerListId = 0; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_NAME (EvQueueNotifyRequest); /* Are Notifies allowed on this object? */ if (!AcpiEvIsNotifyObject (Node)) { return (AE_TYPE); } /* Get the correct notify list type (System or Device) */ if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) { HandlerListId = ACPI_SYSTEM_HANDLER_LIST; } else { HandlerListId = ACPI_DEVICE_HANDLER_LIST; } /* Get the notify object attached to the namespace Node */ ObjDesc = AcpiNsGetAttachedObject (Node); if (ObjDesc) { /* We have an attached object, Get the correct handler list */ HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; } /* * If there is no notify handler (Global or Local) * for this object, just ignore the notify */ if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", AcpiUtGetNodeName (Node), NotifyValue, Node)); return (AE_OK); } /* Setup notify info and schedule the notify dispatcher */ Info = AcpiUtCreateGenericState (); if (!Info) { return (AE_NO_MEMORY); } Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; Info->Notify.Node = Node; Info->Notify.Value = (UINT16) NotifyValue; Info->Notify.HandlerListId = HandlerListId; Info->Notify.HandlerListHead = HandlerListHead; Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Dispatching Notify on [%4.4s] (%s) Value 0x%2.2X (%s) Node %p\n", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), NotifyValue, AcpiUtGetNotifyName (NotifyValue, ACPI_TYPE_ANY), Node)); Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, AcpiEvNotifyDispatch, Info); if (ACPI_FAILURE (Status)) { AcpiUtDeleteGenericState (Info); } return (Status); }
ACPI_STATUS AcpiUtUpdateObjectReference ( ACPI_OPERAND_OBJECT *Object, UINT16 Action) { ACPI_STATUS Status = AE_OK; ACPI_GENERIC_STATE *StateList = NULL; ACPI_OPERAND_OBJECT *NextObject = NULL; ACPI_OPERAND_OBJECT *PrevObject; ACPI_GENERIC_STATE *State; UINT32 i; ACPI_FUNCTION_NAME (UtUpdateObjectReference); while (Object) { /* Make sure that this isn't a namespace handle */ if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) { ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p is NS handle\n", Object)); return (AE_OK); } /* * All sub-objects must have their reference count incremented * also. Different object types have different subobjects. */ switch (Object->Common.Type) { case ACPI_TYPE_DEVICE: case ACPI_TYPE_PROCESSOR: case ACPI_TYPE_POWER: case ACPI_TYPE_THERMAL: /* * Update the notify objects for these types (if present) * Two lists, system and device notify handlers. */ for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { PrevObject = Object->CommonNotify.NotifyList[i]; while (PrevObject) { NextObject = PrevObject->Notify.Next[i]; AcpiUtUpdateRefCount (PrevObject, Action); PrevObject = NextObject; } } break; case ACPI_TYPE_PACKAGE: /* * We must update all the sub-objects of the package, * each of whom may have their own sub-objects. */ for (i = 0; i < Object->Package.Count; i++) { /* * Null package elements are legal and can be simply * ignored. */ NextObject = Object->Package.Elements[i]; if (!NextObject) { continue; } switch (NextObject->Common.Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_STRING: case ACPI_TYPE_BUFFER: /* * For these very simple sub-objects, we can just * update the reference count here and continue. * Greatly increases performance of this operation. */ AcpiUtUpdateRefCount (NextObject, Action); break; default: /* * For complex sub-objects, push them onto the stack * for later processing (this eliminates recursion.) */ Status = AcpiUtCreateUpdateStateAndPush ( NextObject, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; } } NextObject = NULL; break; case ACPI_TYPE_BUFFER_FIELD: NextObject = Object->BufferField.BufferObj; break; case ACPI_TYPE_LOCAL_REGION_FIELD: NextObject = Object->Field.RegionObj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: NextObject = Object->BankField.BankObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->BankField.RegionObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_INDEX_FIELD: NextObject = Object->IndexField.IndexObj; Status = AcpiUtCreateUpdateStateAndPush ( Object->IndexField.DataObj, Action, &StateList); if (ACPI_FAILURE (Status)) { goto ErrorExit; } break; case ACPI_TYPE_LOCAL_REFERENCE: /* * The target of an Index (a package, string, or buffer) or a named * reference must track changes to the ref count of the index or * target object. */ if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || (Object->Reference.Class== ACPI_REFCLASS_NAME)) { NextObject = Object->Reference.Object; } break; case ACPI_TYPE_REGION: default: break; /* No subobjects for all other types */ } /* * Now we can update the count in the main object. This can only * happen after we update the sub-objects in case this causes the * main object to be deleted. */ AcpiUtUpdateRefCount (Object, Action); Object = NULL; /* Move on to the next object to be updated */ if (NextObject) { Object = NextObject; NextObject = NULL; } else if (StateList) { State = AcpiUtPopGenericState (&StateList); Object = State->Update.Object; AcpiUtDeleteGenericState (State); } } return (AE_OK); ErrorExit: ACPI_EXCEPTION ((AE_INFO, Status, "Could not update object reference count")); /* Free any stacked Update State objects */ while (StateList) { State = AcpiUtPopGenericState (&StateList); AcpiUtDeleteGenericState (State); } return (Status); }
static void AcpiUtUpdateRefCount ( ACPI_OPERAND_OBJECT *Object, UINT32 Action) { UINT16 OriginalCount; UINT16 NewCount = 0; ACPI_CPU_FLAGS LockFlags; ACPI_FUNCTION_NAME (UtUpdateRefCount); if (!Object) { return; } /* * Always get the reference count lock. Note: Interpreter and/or * Namespace is not always locked when this function is called. */ LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock); OriginalCount = Object->Common.ReferenceCount; /* Perform the reference count action (increment, decrement) */ switch (Action) { case REF_INCREMENT: NewCount = OriginalCount + 1; Object->Common.ReferenceCount = NewCount; AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); /* The current reference count should never be zero here */ if (!OriginalCount) { ACPI_WARNING ((AE_INFO, "Obj %p, Reference Count was zero before increment\n", Object)); } ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Type %.2X Refs %.2X [Incremented]\n", Object, Object->Common.Type, NewCount)); break; case REF_DECREMENT: /* The current reference count must be non-zero */ if (OriginalCount) { NewCount = OriginalCount - 1; Object->Common.ReferenceCount = NewCount; } AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); if (!OriginalCount) { ACPI_WARNING ((AE_INFO, "Obj %p, Reference Count is already zero, cannot decrement\n", Object)); } ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Obj %p Type %.2X Refs %.2X [Decremented]\n", Object, Object->Common.Type, NewCount)); /* Actually delete the object on a reference count of zero */ if (NewCount == 0) { AcpiUtDeleteInternalObj (Object); } break; default: AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)", Action)); return; } /* * Sanity check the reference count, for debug purposes only. * (A deleted object will have a huge reference count) */ if (NewCount > ACPI_MAX_REFERENCE_COUNT) { ACPI_WARNING ((AE_INFO, "Large Reference Count (0x%X) in object %p, Type=0x%.2X", NewCount, Object, Object->Common.Type)); } }
static ACPI_STATUS AcpiHwValidateIoRequest ( ACPI_IO_ADDRESS Address, UINT32 BitWidth) { UINT32 i; UINT32 ByteWidth; ACPI_IO_ADDRESS LastAddress; const ACPI_PORT_INFO *PortInfo; ACPI_FUNCTION_NAME (HwValidateIoRequest); /* Supported widths are 8/16/32 */ if ((BitWidth != 8) && (BitWidth != 16) && (BitWidth != 32)) { ACPI_ERROR ((AE_INFO, "Bad BitWidth parameter: %8.8X", BitWidth)); return (AE_BAD_PARAMETER); } PortInfo = AcpiProtectedPorts; ByteWidth = ACPI_DIV_8 (BitWidth); LastAddress = Address + ByteWidth - 1; ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X", ACPI_FORMAT_UINT64 (Address), ACPI_FORMAT_UINT64 (LastAddress), ByteWidth)); /* Maximum 16-bit address in I/O space */ if (LastAddress > ACPI_UINT16_MAX) { ACPI_ERROR ((AE_INFO, "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X", ACPI_FORMAT_UINT64 (Address), ByteWidth)); return (AE_LIMIT); } /* Exit if requested address is not within the protected port table */ if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End) { return (AE_OK); } /* Check request against the list of protected I/O ports */ for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++) { /* * Check if the requested address range will write to a reserved * port. There are four cases to consider: * * 1) Address range is contained completely in the port address range * 2) Address range overlaps port range at the port range start * 3) Address range overlaps port range at the port range end * 4) Address range completely encompasses the port range */ if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start)) { /* Port illegality may depend on the _OSI calls made by the BIOS */ if (AcpiGbl_OsiData >= PortInfo->OsiDependency) { ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)", ACPI_FORMAT_UINT64 (Address), ByteWidth, PortInfo->Name, PortInfo->Start, PortInfo->End)); return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS); } } /* Finished if address range ends before the end of this port */ if (LastAddress <= PortInfo->End) { break; } } return (AE_OK); }
acpi_status acpi_ut_acquire_mutex ( acpi_mutex_handle mutex_id) { acpi_status status; u32 this_thread_id; ACPI_FUNCTION_NAME ("ut_acquire_mutex"); if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } this_thread_id = acpi_os_get_thread_id (); #ifdef ACPI_MUTEX_DEBUG { u32 i; /* * Mutex debug code, for internal debugging only. * * Deadlock prevention. Check if this thread owns any mutexes of value * greater than or equal to this one. If so, the thread has violated * the mutex ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] already acquired by this thread [%X]\n", acpi_ut_get_mutex_name (mutex_id), this_thread_id)); return (AE_ALREADY_ACQUIRED); } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid acquire order: Thread %X owns [%s], wants [%s]\n", this_thread_id, acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); return (AE_ACQUIRE_DEADLOCK); } } } #endif ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X attempting to acquire Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); status = acpi_os_wait_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1, ACPI_WAIT_FOREVER); if (ACPI_SUCCESS (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X acquired Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); acpi_gbl_mutex_info[mutex_id].use_count++; acpi_gbl_mutex_info[mutex_id].owner_id = this_thread_id; } else { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not acquire Mutex [%s] %s\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id), acpi_format_exception (status))); } return (status); }
static ACPI_STATUS AcpiNsInitOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OBJECT_TYPE Type; ACPI_STATUS Status = AE_OK; ACPI_INIT_WALK_INFO *Info = (ACPI_INIT_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_FUNCTION_NAME (NsInitOneObject); Info->ObjectCount++; /* And even then, we are only interested in a few object types */ Type = AcpiNsGetType (ObjHandle); ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { return (AE_OK); } /* Increment counters for object types we are looking for */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionCount++; break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldCount++; break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldCount++; break; case ACPI_TYPE_BUFFER: Info->BufferCount++; break; case ACPI_TYPE_PACKAGE: Info->PackageCount++; break; default: /* No init required, just exit now */ return (AE_OK); } /* If the object is already initialized, nothing else to do */ if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { return (AE_OK); } /* Must lock the interpreter before executing AML code */ AcpiExEnterInterpreter (); /* * Each of these types can contain executable AML code within the * declaration. */ switch (Type) { case ACPI_TYPE_REGION: Info->OpRegionInit++; Status = AcpiDsGetRegionArguments (ObjDesc); break; case ACPI_TYPE_BUFFER_FIELD: Info->FieldInit++; Status = AcpiDsGetBufferFieldArguments (ObjDesc); break; case ACPI_TYPE_LOCAL_BANK_FIELD: Info->FieldInit++; Status = AcpiDsGetBankFieldArguments (ObjDesc); break; case ACPI_TYPE_BUFFER: Info->BufferInit++; Status = AcpiDsGetBufferArguments (ObjDesc); break; case ACPI_TYPE_PACKAGE: Info->PackageInit++; Status = AcpiDsGetPackageArguments (ObjDesc); break; default: /* No other types can get here */ break; } if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not execute arguments for [%4.4s] (%s)", AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); } /* * We ignore errors from above, and always return OK, since we don't want * to abort the walk on any single error. */ AcpiExExitInterpreter (); return (AE_OK); }
acpi_status acpi_ut_release_mutex ( acpi_mutex_handle mutex_id) { acpi_status status; u32 i; u32 this_thread_id; ACPI_FUNCTION_NAME ("ut_release_mutex"); this_thread_id = acpi_os_get_thread_id (); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X releasing Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); if (mutex_id > MAX_MUTEX) { return (AE_BAD_PARAMETER); } /* * Mutex must be acquired in order to release it! */ if (acpi_gbl_mutex_info[mutex_id].owner_id == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] is not acquired, cannot release\n", acpi_ut_get_mutex_name (mutex_id))); return (AE_NOT_ACQUIRED); } /* * Deadlock prevention. Check if this thread owns any mutexes of value * greater than this one. If so, the thread has violated the mutex * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = mutex_id; i < MAX_MUTEX; i++) { if (acpi_gbl_mutex_info[i].owner_id == this_thread_id) { if (i == mutex_id) { continue; } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid release order: owns [%s], releasing [%s]\n", acpi_ut_get_mutex_name (i), acpi_ut_get_mutex_name (mutex_id))); return (AE_RELEASE_DEADLOCK); } } /* Mark unlocked FIRST */ acpi_gbl_mutex_info[mutex_id].owner_id = ACPI_MUTEX_NOT_ACQUIRED; status = acpi_os_signal_semaphore (acpi_gbl_mutex_info[mutex_id].mutex, 1); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id), acpi_format_exception (status))); } else { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", this_thread_id, acpi_ut_get_mutex_name (mutex_id))); } return (status); }
ACPI_STATUS AcpiUtReleaseMutex ( ACPI_MUTEX_HANDLE MutexId) { ACPI_STATUS Status; UINT32 i; UINT32 ThisThreadId; ACPI_FUNCTION_NAME ("UtReleaseMutex"); ThisThreadId = AcpiOsGetThreadId (); ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X releasing Mutex [%s]\n", ThisThreadId, AcpiUtGetMutexName (MutexId))); if (MutexId > MAX_MTX) { return (AE_BAD_PARAMETER); } /* * Mutex must be acquired in order to release it! */ if (AcpiGbl_AcpiMutexInfo[MutexId].OwnerId == ACPI_MUTEX_NOT_ACQUIRED) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Mutex [%s] is not acquired, cannot release\n", AcpiUtGetMutexName (MutexId))); return (AE_NOT_ACQUIRED); } /* * Deadlock prevention. Check if this thread owns any mutexes of value * greater than this one. If so, the thread has violated the mutex * ordering rule. This indicates a coding error somewhere in * the ACPI subsystem code. */ for (i = MutexId; i < MAX_MTX; i++) { if (AcpiGbl_AcpiMutexInfo[i].OwnerId == ThisThreadId) { if (i == MutexId) { continue; } ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Invalid release order: owns [%s], releasing [%s]\n", AcpiUtGetMutexName (i), AcpiUtGetMutexName (MutexId))); return (AE_RELEASE_DEADLOCK); } } /* Mark unlocked FIRST */ AcpiGbl_AcpiMutexInfo[MutexId].OwnerId = ACPI_MUTEX_NOT_ACQUIRED; Status = AcpiOsSignalSemaphore (AcpiGbl_AcpiMutexInfo[MutexId].Mutex, 1); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Thread %X could not release Mutex [%s] %s\n", ThisThreadId, AcpiUtGetMutexName (MutexId), AcpiFormatException (Status))); } else { ACPI_DEBUG_PRINT ((ACPI_DB_MUTEX, "Thread %X released Mutex [%s]\n", ThisThreadId, AcpiUtGetMutexName (MutexId))); } return (Status); }
ACPI_STATUS AcpiDsResultPop ( ACPI_OPERAND_OBJECT **Object, ACPI_WALK_STATE *WalkState) { UINT32 Index; ACPI_GENERIC_STATE *State; ACPI_STATUS Status; ACPI_FUNCTION_NAME (DsResultPop); State = WalkState->Results; /* Incorrect state of result stack */ if (State && !WalkState->ResultCount) { ACPI_ERROR ((AE_INFO, "No results on result stack")); return (AE_AML_INTERNAL); } if (!State && WalkState->ResultCount) { ACPI_ERROR ((AE_INFO, "No result state for result stack")); return (AE_AML_INTERNAL); } /* Empty result stack */ if (!State) { ACPI_ERROR ((AE_INFO, "Result stack is empty! State=%p", WalkState)); return (AE_AML_NO_RETURN_VALUE); } /* Return object of the top element and clean that top element result stack */ WalkState->ResultCount--; Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; *Object = State->Results.ObjDesc [Index]; if (!*Object) { ACPI_ERROR ((AE_INFO, "No result objects on result stack, State=%p", WalkState)); return (AE_AML_NO_RETURN_VALUE); } State->Results.ObjDesc [Index] = NULL; if (Index == 0) { Status = AcpiDsResultStackPop (WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] Index=%X State=%p Num=%X\n", *Object, AcpiUtGetObjectTypeName (*Object), Index, WalkState, WalkState->ResultCount)); return (AE_OK); }
static ACPI_STATUS AcpiEvInstallHandler ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_OPERAND_OBJECT *HandlerObj; ACPI_OPERAND_OBJECT *NextHandlerObj; ACPI_OPERAND_OBJECT *ObjDesc; ACPI_NAMESPACE_NODE *Node; ACPI_STATUS Status; ACPI_FUNCTION_NAME (EvInstallHandler); HandlerObj = (ACPI_OPERAND_OBJECT *) Context; /* Parameter validation */ if (!HandlerObj) { return (AE_OK); } /* Convert and validate the device handle */ Node = AcpiNsValidateHandle (ObjHandle); if (!Node) { return (AE_BAD_PARAMETER); } /* * We only care about regions and objects that are allowed to have * address space handlers */ if ((Node->Type != ACPI_TYPE_DEVICE) && (Node->Type != ACPI_TYPE_REGION) && (Node != AcpiGbl_RootNode)) { return (AE_OK); } /* Check for an existing internal object */ ObjDesc = AcpiNsGetAttachedObject (Node); if (!ObjDesc) { /* No object, just exit */ return (AE_OK); } /* Devices are handled different than regions */ if (ObjDesc->Common.Type == ACPI_TYPE_DEVICE) { /* Check if this Device already has a handler for this address space */ NextHandlerObj = ObjDesc->Device.Handler; while (NextHandlerObj) { /* Found a handler, is it for the same address space? */ if (NextHandlerObj->AddressSpace.SpaceId == HandlerObj->AddressSpace.SpaceId) { ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Found handler for region [%s] in device %p(%p) " "handler %p\n", AcpiUtGetRegionName (HandlerObj->AddressSpace.SpaceId), ObjDesc, NextHandlerObj, HandlerObj)); /* * Since the object we found it on was a device, then it * means that someone has already installed a handler for * the branch of the namespace from this device on. Just * bail out telling the walk routine to not traverse this * branch. This preserves the scoping rule for handlers. */ return (AE_CTRL_DEPTH); } /* Walk the linked list of handlers attached to this device */ NextHandlerObj = NextHandlerObj->AddressSpace.Next; } /* * As long as the device didn't have a handler for this space we * don't care about it. We just ignore it and proceed. */ return (AE_OK); } /* Object is a Region */ if (ObjDesc->Region.SpaceId != HandlerObj->AddressSpace.SpaceId) { /* This region is for a different address space, just ignore it */ return (AE_OK); } /* * Now we have a region and it is for the handler's address space type. * * First disconnect region for any previous handler (if any) */ AcpiEvDetachRegion (ObjDesc, FALSE); /* Connect the region to the new handler */ Status = AcpiEvAttachRegion (HandlerObj, ObjDesc, FALSE); return (Status); }
ACPI_STATUS AcpiDsResultPush ( ACPI_OPERAND_OBJECT *Object, ACPI_WALK_STATE *WalkState) { ACPI_GENERIC_STATE *State; ACPI_STATUS Status; UINT32 Index; ACPI_FUNCTION_NAME (DsResultPush); if (WalkState->ResultCount > WalkState->ResultSize) { ACPI_ERROR ((AE_INFO, "Result stack is full")); return (AE_AML_INTERNAL); } else if (WalkState->ResultCount == WalkState->ResultSize) { /* Extend the result stack */ Status = AcpiDsResultStackPush (WalkState); if (ACPI_FAILURE (Status)) { ACPI_ERROR ((AE_INFO, "Failed to extend the result stack")); return (Status); } } if (!(WalkState->ResultCount < WalkState->ResultSize)) { ACPI_ERROR ((AE_INFO, "No free elements in result stack")); return (AE_AML_INTERNAL); } State = WalkState->Results; if (!State) { ACPI_ERROR ((AE_INFO, "No result stack frame during push")); return (AE_AML_INTERNAL); } if (!Object) { ACPI_ERROR ((AE_INFO, "Null Object! Obj=%p State=%p Num=%u", Object, WalkState, WalkState->ResultCount)); return (AE_BAD_PARAMETER); } /* Assign the address of object to the top free element of result stack */ Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; State->Results.ObjDesc [Index] = Object; WalkState->ResultCount++; ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object), WalkState, WalkState->ResultCount, WalkState->CurrentResult)); return (AE_OK); }
static ACPI_STATUS LdNamespace2Begin ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_WALK_STATE *WalkState = (ACPI_WALK_STATE *) Context; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; ACPI_OBJECT_TYPE ObjectType; BOOLEAN ForceNewScope = FALSE; ACPI_PARSE_OBJECT *Arg; char *Path; ACPI_NAMESPACE_NODE *TargetNode; ACPI_FUNCTION_NAME (LdNamespace2Begin); ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op %p [%s]\n", Op, Op->Asl.ParseOpName)); /* Ignore Ops with no namespace node */ Node = Op->Asl.Node; if (!Node) { return (AE_OK); } /* Get the type to determine if we should push the scope */ if ((Op->Asl.ParseOpcode == PARSEOP_DEFAULT_ARG) && (Op->Asl.CompileFlags == NODE_IS_RESOURCE_DESC)) { ObjectType = ACPI_TYPE_LOCAL_RESOURCE; } else { ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); } /* Push scope for Resource Templates */ if (Op->Asl.ParseOpcode == PARSEOP_NAME) { if (Op->Asl.CompileFlags & NODE_IS_RESOURCE_DESC) { ForceNewScope = TRUE; } } /* Push the scope stack */ if (ForceNewScope || AcpiNsOpensScope (ObjectType)) { Status = AcpiDsScopeStackPush (Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } if (Op->Asl.ParseOpcode == PARSEOP_ALIAS) { /* Complete the alias node by getting and saving the target node */ /* First child is the alias target */ Arg = Op->Asl.Child; /* Get the target pathname */ Path = Arg->Asl.Namepath; if (!Path) { Status = UtInternalizeName (Arg->Asl.ExternalName, &Path); if (ACPI_FAILURE (Status)) { return (Status); } } /* Get the NS node associated with the target. It must exist. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, WalkState, &TargetNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { AslError (ASL_ERROR, ASL_MSG_NOT_FOUND, Op, Op->Asl.ExternalName); /* * The name was not found, go ahead and create it. * This prevents more errors later. */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_LOAD_PASS1, ACPI_NS_NO_UPSEARCH, WalkState, &(Node)); return (AE_OK); } AslCoreSubsystemError (Op, Status, "Failure from namespace lookup", FALSE); return (AE_OK); } /* Save the target node within the alias node */ Node->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); } return (AE_OK); }
static ACPI_STATUS AcpiNsRepair_FDE ( ACPI_PREDEFINED_DATA *Data, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_OPERAND_OBJECT *BufferObject; UINT8 *ByteBuffer; UINT32 *DwordBuffer; UINT32 i; ACPI_FUNCTION_NAME (NsRepair_FDE); switch (ReturnObject->Common.Type) { case ACPI_TYPE_BUFFER: /* This is the expected type. Length should be (at least) 5 DWORDs */ if (ReturnObject->Buffer.Length >= ACPI_FDE_DWORD_BUFFER_SIZE) { return (AE_OK); } /* We can only repair if we have exactly 5 BYTEs */ if (ReturnObject->Buffer.Length != ACPI_FDE_BYTE_BUFFER_SIZE) { ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Incorrect return buffer length %u, expected %u", ReturnObject->Buffer.Length, ACPI_FDE_DWORD_BUFFER_SIZE)); return (AE_AML_OPERAND_TYPE); } /* Create the new (larger) buffer object */ BufferObject = AcpiUtCreateBufferObject (ACPI_FDE_DWORD_BUFFER_SIZE); if (!BufferObject) { return (AE_NO_MEMORY); } /* Expand each byte to a DWORD */ ByteBuffer = ReturnObject->Buffer.Pointer; DwordBuffer = ACPI_CAST_PTR (UINT32, BufferObject->Buffer.Pointer); for (i = 0; i < ACPI_FDE_FIELD_COUNT; i++) { *DwordBuffer = (UINT32) *ByteBuffer; DwordBuffer++; ByteBuffer++; } ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, "%s Expanded Byte Buffer to expected DWord Buffer\n", Data->Pathname)); break; default: return (AE_AML_OPERAND_TYPE); } /* Delete the original return object, return the new buffer object */ AcpiUtRemoveReference (ReturnObject); *ReturnObjectPtr = BufferObject; Data->Flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); }
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); } }
static ACPI_STATUS AcpiNsRepair_HID ( ACPI_PREDEFINED_DATA *Data, ACPI_OPERAND_OBJECT **ReturnObjectPtr) { ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; ACPI_OPERAND_OBJECT *NewString; char *Source; char *Dest; ACPI_FUNCTION_NAME (NsRepair_HID); /* We only care about string _HID objects (not integers) */ if (ReturnObject->Common.Type != ACPI_TYPE_STRING) { return (AE_OK); } if (ReturnObject->String.Length == 0) { ACPI_WARN_PREDEFINED ((AE_INFO, Data->Pathname, Data->NodeFlags, "Invalid zero-length _HID or _CID string")); /* Return AE_OK anyway, let driver handle it */ Data->Flags |= ACPI_OBJECT_REPAIRED; return (AE_OK); } /* It is simplest to always create a new string object */ NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); if (!NewString) { return (AE_NO_MEMORY); } /* * Remove a leading asterisk if present. For some unknown reason, there * are many machines in the field that contains IDs like this. * * Examples: "*PNP0C03", "*ACPI0003" */ Source = ReturnObject->String.Pointer; if (*Source == '*') { Source++; NewString->String.Length--; ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, "%s: Removed invalid leading asterisk\n", Data->Pathname)); } /* * Copy and uppercase the string. From the ACPI 5.0 specification: * * A valid PNP ID must be of the form "AAA####" where A is an uppercase * letter and # is a hex digit. A valid ACPI ID must be of the form * "NNNN####" where N is an uppercase letter or decimal digit, and * # is a hex digit. */ for (Dest = NewString->String.Pointer; *Source; Dest++, Source++) { *Dest = (char) ACPI_TOUPPER (*Source); } AcpiUtRemoveReference (ReturnObject); *ReturnObjectPtr = NewString; return (AE_OK); }
ACPI_STATUS AcpiNsDumpOneObject ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_WALK_INFO *Info = (ACPI_WALK_INFO *) Context; ACPI_NAMESPACE_NODE *ThisNode; ACPI_OPERAND_OBJECT *ObjDesc = NULL; ACPI_OBJECT_TYPE ObjType; ACPI_OBJECT_TYPE Type; UINT32 BytesToDump; UINT32 DbgLevel; UINT32 i; ACPI_FUNCTION_NAME (NsDumpOneObject); /* Is output enabled? */ if (!(AcpiDbgLevel & Info->DebugLevel)) { return (AE_OK); } if (!ObjHandle) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Null object handle\n")); return (AE_OK); } ThisNode = AcpiNsValidateHandle (ObjHandle); if (!ThisNode) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Invalid object handle %p\n", ObjHandle)); return (AE_OK); } Type = ThisNode->Type; /* Check if the owner matches */ if ((Info->OwnerId != ACPI_OWNER_ID_MAX) && (Info->OwnerId != ThisNode->OwnerId)) { return (AE_OK); } if (!(Info->DisplayType & ACPI_DISPLAY_SHORT)) { /* Indent the object according to the level */ AcpiOsPrintf ("%2d%*s", (UINT32) Level - 1, (int) Level * 2, " "); /* Check the node type and name */ if (Type > ACPI_TYPE_LOCAL_MAX) { ACPI_WARNING ((AE_INFO, "Invalid ACPI Object Type 0x%08X", Type)); } AcpiOsPrintf ("%4.4s", AcpiUtGetNodeName (ThisNode)); } /* Now we can print out the pertinent information */ AcpiOsPrintf (" %-12s %p %2.2X ", AcpiUtGetTypeName (Type), ThisNode, ThisNode->OwnerId); DbgLevel = AcpiDbgLevel; AcpiDbgLevel = 0; ObjDesc = AcpiNsGetAttachedObject (ThisNode); AcpiDbgLevel = DbgLevel; /* Temp nodes are those nodes created by a control method */ if (ThisNode->Flags & ANOBJ_TEMPORARY) { AcpiOsPrintf ("(T) "); } switch (Info->DisplayType & ACPI_DISPLAY_MASK) { case ACPI_DISPLAY_SUMMARY: if (!ObjDesc) { /* No attached object. Some types should always have an object */ switch (Type) { case ACPI_TYPE_INTEGER: case ACPI_TYPE_PACKAGE: case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: case ACPI_TYPE_METHOD: AcpiOsPrintf ("<No attached object>"); break; default: break; } AcpiOsPrintf ("\n"); return (AE_OK); } switch (Type) { case ACPI_TYPE_PROCESSOR: AcpiOsPrintf ("ID %02X Len %02X Addr %8.8X%8.8X\n", ObjDesc->Processor.ProcId, ObjDesc->Processor.Length, ACPI_FORMAT_UINT64 (ObjDesc->Processor.Address)); break; case ACPI_TYPE_DEVICE: AcpiOsPrintf ("Notify Object: %p\n", ObjDesc); break; case ACPI_TYPE_METHOD: AcpiOsPrintf ("Args %X Len %.4X Aml %p\n", (UINT32) ObjDesc->Method.ParamCount, ObjDesc->Method.AmlLength, ObjDesc->Method.AmlStart); break; case ACPI_TYPE_INTEGER: AcpiOsPrintf ("= %8.8X%8.8X\n", ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); break; case ACPI_TYPE_PACKAGE: if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf ("Elements %.2X\n", ObjDesc->Package.Count); } else { AcpiOsPrintf ("[Length not yet evaluated]\n"); } break; case ACPI_TYPE_BUFFER: if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf ("Len %.2X", ObjDesc->Buffer.Length); /* Dump some of the buffer */ if (ObjDesc->Buffer.Length > 0) { AcpiOsPrintf (" ="); for (i = 0; (i < ObjDesc->Buffer.Length && i < 12); i++) { AcpiOsPrintf (" %.2hX", ObjDesc->Buffer.Pointer[i]); } } AcpiOsPrintf ("\n"); } else { AcpiOsPrintf ("[Length not yet evaluated]\n"); } break; case ACPI_TYPE_STRING: AcpiOsPrintf ("Len %.2X ", ObjDesc->String.Length); AcpiUtPrintString (ObjDesc->String.Pointer, 32); AcpiOsPrintf ("\n"); break; case ACPI_TYPE_REGION: AcpiOsPrintf ("[%s]", AcpiUtGetRegionName (ObjDesc->Region.SpaceId)); if (ObjDesc->Region.Flags & AOPOBJ_DATA_VALID) { AcpiOsPrintf (" Addr %8.8X%8.8X Len %.4X\n", ACPI_FORMAT_UINT64 (ObjDesc->Region.Address), ObjDesc->Region.Length); } else { AcpiOsPrintf (" [Address/Length not yet evaluated]\n"); } break; case ACPI_TYPE_LOCAL_REFERENCE: AcpiOsPrintf ("[%s]\n", AcpiUtGetReferenceName (ObjDesc)); break; case ACPI_TYPE_BUFFER_FIELD: if (ObjDesc->BufferField.BufferObj && ObjDesc->BufferField.BufferObj->Buffer.Node) { AcpiOsPrintf ("Buf [%4.4s]", AcpiUtGetNodeName ( ObjDesc->BufferField.BufferObj->Buffer.Node)); } break; case ACPI_TYPE_LOCAL_REGION_FIELD: AcpiOsPrintf ("Rgn [%4.4s]", AcpiUtGetNodeName ( ObjDesc->CommonField.RegionObj->Region.Node)); break; case ACPI_TYPE_LOCAL_BANK_FIELD: AcpiOsPrintf ("Rgn [%4.4s] Bnk [%4.4s]", AcpiUtGetNodeName ( ObjDesc->CommonField.RegionObj->Region.Node), AcpiUtGetNodeName ( ObjDesc->BankField.BankObj->CommonField.Node)); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: AcpiOsPrintf ("Idx [%4.4s] Dat [%4.4s]", AcpiUtGetNodeName ( ObjDesc->IndexField.IndexObj->CommonField.Node), AcpiUtGetNodeName ( ObjDesc->IndexField.DataObj->CommonField.Node)); break; case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: AcpiOsPrintf ("Target %4.4s (%p)\n", AcpiUtGetNodeName (ObjDesc), ObjDesc); break; default: AcpiOsPrintf ("Object %p\n", ObjDesc); break; } /* Common field handling */ switch (Type) { case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: AcpiOsPrintf (" Off %.3X Len %.2X Acc %.2hd\n", (ObjDesc->CommonField.BaseByteOffset * 8) + ObjDesc->CommonField.StartFieldBitOffset, ObjDesc->CommonField.BitLength, ObjDesc->CommonField.AccessByteWidth); break; default: break; } break; case ACPI_DISPLAY_OBJECTS: AcpiOsPrintf ("O:%p", ObjDesc); if (!ObjDesc) { /* No attached object, we are done */ AcpiOsPrintf ("\n"); return (AE_OK); } AcpiOsPrintf ("(R%u)", ObjDesc->Common.ReferenceCount); switch (Type) { case ACPI_TYPE_METHOD: /* Name is a Method and its AML offset/length are set */ AcpiOsPrintf (" M:%p-%X\n", ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength); break; case ACPI_TYPE_INTEGER: AcpiOsPrintf (" I:%8.8X8.8%X\n", ACPI_FORMAT_UINT64 (ObjDesc->Integer.Value)); break; case ACPI_TYPE_STRING: AcpiOsPrintf (" S:%p-%X\n", ObjDesc->String.Pointer, ObjDesc->String.Length); break; case ACPI_TYPE_BUFFER: AcpiOsPrintf (" B:%p-%X\n", ObjDesc->Buffer.Pointer, ObjDesc->Buffer.Length); break; default: AcpiOsPrintf ("\n"); break; } break; default: AcpiOsPrintf ("\n"); break; } /* If debug turned off, done */ if (!(AcpiDbgLevel & ACPI_LV_VALUES)) { return (AE_OK); } /* If there is an attached object, display it */ DbgLevel = AcpiDbgLevel; AcpiDbgLevel = 0; ObjDesc = AcpiNsGetAttachedObject (ThisNode); AcpiDbgLevel = DbgLevel; /* Dump attached objects */ while (ObjDesc) { ObjType = ACPI_TYPE_INVALID; AcpiOsPrintf ("Attached Object %p: ", ObjDesc); /* Decode the type of attached object and dump the contents */ switch (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc)) { case ACPI_DESC_TYPE_NAMED: AcpiOsPrintf ("(Ptr to Node)\n"); BytesToDump = sizeof (ACPI_NAMESPACE_NODE); ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); break; case ACPI_DESC_TYPE_OPERAND: ObjType = ObjDesc->Common.Type; if (ObjType > ACPI_TYPE_LOCAL_MAX) { AcpiOsPrintf ( "(Pointer to ACPI Object type %.2X [UNKNOWN])\n", ObjType); BytesToDump = 32; } else { AcpiOsPrintf ( "(Pointer to ACPI Object type %.2X [%s])\n", ObjType, AcpiUtGetTypeName (ObjType)); BytesToDump = sizeof (ACPI_OPERAND_OBJECT); } ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); break; default: break; } /* If value is NOT an internal object, we are done */ if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) { goto Cleanup; } /* Valid object, get the pointer to next level, if any */ switch (ObjType) { case ACPI_TYPE_BUFFER: case ACPI_TYPE_STRING: /* * NOTE: takes advantage of common fields between string/buffer */ BytesToDump = ObjDesc->String.Length; ObjDesc = (void *) ObjDesc->String.Pointer; AcpiOsPrintf ("(Buffer/String pointer %p length %X)\n", ObjDesc, BytesToDump); ACPI_DUMP_BUFFER (ObjDesc, BytesToDump); goto Cleanup; case ACPI_TYPE_BUFFER_FIELD: ObjDesc = (ACPI_OPERAND_OBJECT *) ObjDesc->BufferField.BufferObj; break; case ACPI_TYPE_PACKAGE: ObjDesc = (void *) ObjDesc->Package.Elements; break; case ACPI_TYPE_METHOD: ObjDesc = (void *) ObjDesc->Method.AmlStart; break; case ACPI_TYPE_LOCAL_REGION_FIELD: ObjDesc = (void *) ObjDesc->Field.RegionObj; break; case ACPI_TYPE_LOCAL_BANK_FIELD: ObjDesc = (void *) ObjDesc->BankField.RegionObj; break; case ACPI_TYPE_LOCAL_INDEX_FIELD: ObjDesc = (void *) ObjDesc->IndexField.IndexObj; break; default: goto Cleanup; } ObjType = ACPI_TYPE_INVALID; /* Terminate loop after next pass */ } Cleanup: AcpiOsPrintf ("\n"); return (AE_OK); }
static ACPI_STATUS AcpiNsCheckSortedList ( ACPI_PREDEFINED_DATA *Data, ACPI_OPERAND_OBJECT *ReturnObject, UINT32 ExpectedCount, UINT32 SortIndex, UINT8 SortDirection, char *SortKeyName) { UINT32 OuterElementCount; ACPI_OPERAND_OBJECT **OuterElements; ACPI_OPERAND_OBJECT **Elements; ACPI_OPERAND_OBJECT *ObjDesc; UINT32 i; UINT32 PreviousValue; ACPI_FUNCTION_NAME (NsCheckSortedList); /* The top-level object must be a package */ if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) { return (AE_AML_OPERAND_TYPE); } /* * NOTE: assumes list of sub-packages contains no NULL elements. * Any NULL elements should have been removed by earlier call * to AcpiNsRemoveNullElements. */ OuterElements = ReturnObject->Package.Elements; OuterElementCount = ReturnObject->Package.Count; if (!OuterElementCount) { return (AE_AML_PACKAGE_LIMIT); } PreviousValue = 0; if (SortDirection == ACPI_SORT_DESCENDING) { PreviousValue = ACPI_UINT32_MAX; } /* Examine each subpackage */ for (i = 0; i < OuterElementCount; i++) { /* Each element of the top-level package must also be a package */ if ((*OuterElements)->Common.Type != ACPI_TYPE_PACKAGE) { return (AE_AML_OPERAND_TYPE); } /* Each sub-package must have the minimum length */ if ((*OuterElements)->Package.Count < ExpectedCount) { return (AE_AML_PACKAGE_LIMIT); } Elements = (*OuterElements)->Package.Elements; ObjDesc = Elements[SortIndex]; if (ObjDesc->Common.Type != ACPI_TYPE_INTEGER) { return (AE_AML_OPERAND_TYPE); } /* * The list must be sorted in the specified order. If we detect a * discrepancy, sort the entire list. */ if (((SortDirection == ACPI_SORT_ASCENDING) && (ObjDesc->Integer.Value < PreviousValue)) || ((SortDirection == ACPI_SORT_DESCENDING) && (ObjDesc->Integer.Value > PreviousValue))) { AcpiNsSortList (ReturnObject->Package.Elements, OuterElementCount, SortIndex, SortDirection); Data->Flags |= ACPI_OBJECT_REPAIRED; ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, "%s: Repaired unsorted list - now sorted by %s\n", Data->Pathname, SortKeyName)); return (AE_OK); } PreviousValue = (UINT32) ObjDesc->Integer.Value; OuterElements++; } return (AE_OK); }
static ACPI_STATUS OptBuildShortestPath ( ACPI_PARSE_OBJECT *Op, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE *CurrentNode, ACPI_NAMESPACE_NODE *TargetNode, ACPI_BUFFER *CurrentPath, ACPI_BUFFER *TargetPath, ACPI_SIZE AmlNameStringLength, UINT8 IsDeclaration, char **ReturnNewPath) { UINT32 NumCommonSegments; UINT32 MaxCommonSegments; UINT32 Index; UINT32 NumCarats; UINT32 i; char *NewPath; char *NewPathExternal; ACPI_NAMESPACE_NODE *Node; ACPI_GENERIC_STATE ScopeInfo; ACPI_STATUS Status; BOOLEAN SubPath = FALSE; ACPI_FUNCTION_NAME (OptBuildShortestPath); ScopeInfo.Scope.Node = CurrentNode; /* * Determine the maximum number of NameSegs that the Target and Current paths * can possibly have in common. (To optimize, we have to have at least 1) * * Note: The external NamePath string lengths are always a multiple of 5 * (ACPI_NAME_SIZE + separator) */ MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH; if (CurrentPath->Length < TargetPath->Length) { MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH; } /* * Determine how many NameSegs the two paths have in common. * (Starting from the root) */ for (NumCommonSegments = 0; NumCommonSegments < MaxCommonSegments; NumCommonSegments++) { /* Compare two single NameSegs */ if (!ACPI_COMPARE_NAME ( &((char *) TargetPath->Pointer)[ (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1], &((char *) CurrentPath->Pointer)[ (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1])) { /* Mismatch */ break; } } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u", NumCommonSegments)); /* There must be at least 1 common NameSeg in order to optimize */ if (NumCommonSegments == 0) { return (AE_NOT_FOUND); } if (NumCommonSegments == MaxCommonSegments) { if (CurrentPath->Length == TargetPath->Length) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH")); return (AE_NOT_FOUND); } else { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH")); SubPath = TRUE; } } /* Determine how many prefix Carats are required */ NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) - NumCommonSegments; /* * Construct a new target string */ NewPathExternal = ACPI_ALLOCATE_ZEROED ( TargetPath->Length + NumCarats + 1); /* Insert the Carats into the Target string */ for (i = 0; i < NumCarats; i++) { NewPathExternal[i] = AML_PARENT_PREFIX; } /* * Copy only the necessary (optimal) segments from the original * target string */ Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1; /* Special handling for exact subpath in a name declaration */ if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length)) { /* * The current path is longer than the target, and the target is a * subpath of the current path. We must include one more NameSeg of * the target path */ Index -= ACPI_PATH_SEGMENT_LENGTH; /* Special handling for Scope() operator */ if (Op->Asl.AmlOpcode == AML_SCOPE_OP) { NewPathExternal[i] = AML_PARENT_PREFIX; i++; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)")); } } /* Make sure we haven't gone off the end of the target path */ if (Index > TargetPath->Length) { Index = TargetPath->Length; } ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal)); /* * Internalize the new target string and check it against the original * string to make sure that this is in fact an optimization. If the * original string is already optimal, there is no point in continuing. */ Status = AcpiNsInternalizeName (NewPathExternal, &NewPath); if (ACPI_FAILURE (Status)) { AslCoreSubsystemError (Op, Status, "Internalizing new NamePath", ASL_NO_ABORT); ACPI_FREE (NewPathExternal); return (Status); } if (ACPI_STRLEN (NewPath) >= AmlNameStringLength) { ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " NOT SHORTER (New %u old %u)", (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength)); ACPI_FREE (NewPathExternal); return (AE_NOT_FOUND); } /* * Check to make sure that the optimization finds the node we are * looking for. This is simply a sanity check on the new * path that has been created. */ Status = AcpiNsLookup (&ScopeInfo, NewPath, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node)); if (ACPI_SUCCESS (Status)) { /* Found the namepath, but make sure the node is correct */ if (Node == TargetNode) { /* The lookup matched the node, accept this optimization */ AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION, Op, NewPathExternal); *ReturnNewPath = NewPath; } else { /* Node is not correct, do not use this optimization */ Status = AE_NOT_FOUND; ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE")); AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, "Not using optimized name - found wrong node"); } } else { /* The lookup failed, we obviously cannot use this optimization */ ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND")); AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op, "Not using optimized name - did not find node"); } ACPI_FREE (NewPathExternal); return (Status); }
UINT32 AcpiEvGpeDetect ( ACPI_GPE_XRUPT_INFO *GpeXruptList) { ACPI_STATUS Status; ACPI_GPE_BLOCK_INFO *GpeBlock; ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; UINT8 EnabledStatusByte; UINT32 StatusReg; UINT32 EnableReg; ACPI_CPU_FLAGS Flags; UINT32 i; UINT32 j; ACPI_FUNCTION_NAME (EvGpeDetect); /* Check for the case where there are no GPEs */ if (!GpeXruptList) { return (IntStatus); } /* * We need to obtain the GPE lock for both the data structs and registers * Note: Not necessary to obtain the hardware lock, since the GPE * registers are owned by the GpeLock. */ Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); /* Examine all GPE blocks attached to this interrupt level */ GpeBlock = GpeXruptList->GpeBlockListHead; while (GpeBlock) { /* * Read all of the 8-bit GPE status and enable registers in this GPE * block, saving all of them. Find all currently active GP events. */ for (i = 0; i < GpeBlock->RegisterCount; i++) { /* Get the next status/enable pair */ GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; /* * Optimization: If there are no GPEs enabled within this * register, we can safely ignore the entire register. */ if (!(GpeRegisterInfo->EnableForRun | GpeRegisterInfo->EnableForWake)) { continue; } /* Read the Status Register */ Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } /* Read the Enable Register */ Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); if (ACPI_FAILURE (Status)) { goto UnlockAndExit; } ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, "Read GPE Register at GPE%02X: Status=%02X, Enable=%02X\n", GpeRegisterInfo->BaseGpeNumber, StatusReg, EnableReg)); /* Check if there is anything active at all in this register */ EnabledStatusByte = (UINT8) (StatusReg & EnableReg); if (!EnabledStatusByte) { /* No active GPEs in this register, move on */ continue; } /* Now look at the individual GPEs in this byte register */ for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { /* Examine one GPE bit */ if (EnabledStatusByte & (1 << j)) { /* * Found an active GPE. Dispatch the event to a handler * or method. */ IntStatus |= AcpiEvGpeDispatch (GpeBlock->Node, &GpeBlock->EventInfo[((ACPI_SIZE) i * ACPI_GPE_REGISTER_WIDTH) + j], j + GpeRegisterInfo->BaseGpeNumber); } } } GpeBlock = GpeBlock->Next; } UnlockAndExit: AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); return (IntStatus); }