acpi_status acpi_ev_match_gpe_method(acpi_handle obj_handle, u32 level, void *context, void **return_value) { struct acpi_namespace_node *method_node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); struct acpi_gpe_walk_info *walk_info = ACPI_CAST_PTR(struct acpi_gpe_walk_info, context); struct acpi_gpe_event_info *gpe_event_info; u32 gpe_number; char name[ACPI_NAME_SIZE + 1]; u8 type; ACPI_FUNCTION_TRACE(ev_match_gpe_method); /* Check if requested owner_id matches this owner_id */ if ((walk_info->execute_by_owner_id) && (method_node->owner_id != walk_info->owner_id)) { return_ACPI_STATUS(AE_OK); } /* * Match and decode the _Lxx and _Exx GPE method names * * 1) Extract the method name and null terminate it */ ACPI_MOVE_32_TO_32(name, &method_node->name.integer); name[ACPI_NAME_SIZE] = 0; /* 2) Name must begin with an underscore */ if (name[0] != '_') { return_ACPI_STATUS(AE_OK); /* Ignore this method */ } /* * 3) Edge/Level determination is based on the 2nd character * of the method name */ switch (name[1]) { case 'L': type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': type = ACPI_GPE_EDGE_TRIGGERED; break; default: /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Ignoring unknown GPE method type: %s " "(name not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* 4) The last two characters of the name are the hex GPE Number */ gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Could not extract GPE number from name: %s " "(name is not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, walk_info->gpe_block); if (!gpe_event_info) { /* * This gpe_number is not valid for this GPE block, just ignore it. * However, it may be valid for a different GPE block, since GPE0 * and GPE1 methods both appear under \_GPE. */ return_ACPI_STATUS(AE_OK); } if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { /* If there is already a handler, ignore this GPE method */ return_ACPI_STATUS(AE_OK); } if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { /* * If there is already a method, ignore this method. But check * for a type mismatch (if both the _Lxx AND _Exx exist) */ if (type != (gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) { ACPI_ERROR((AE_INFO, "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", gpe_number, gpe_number, gpe_number)); } return_ACPI_STATUS(AE_OK); } /* Disable the GPE in case it's been enabled already. */ (void)acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE); /* * Add the GPE information from above to the gpe_event_info block for * use during dispatch of this GPE. */ gpe_event_info->flags &= ~(ACPI_GPE_DISPATCH_MASK); gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); gpe_event_info->dispatch.method_node = method_node; ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", name, gpe_number)); return_ACPI_STATUS(AE_OK); }
void AcpiUtDumpBuffer2 ( UINT8 *Buffer, UINT32 Count, UINT32 Display) { UINT32 i = 0; UINT32 j; UINT32 Temp32; UINT8 BufChar; if (!Buffer) { AcpiOsPrintf ("Null Buffer Pointer in DumpBuffer!\n"); return; } if ((Count < 4) || (Count & 0x01)) { Display = DB_BYTE_DISPLAY; } /* Nasty little dump buffer routine! */ while (i < Count) { /* Print current offset */ AcpiOsPrintf ("%6.4X: ", i); /* Print 16 hex chars */ for (j = 0; j < 16;) { if (i + j >= Count) { /* Dump fill spaces */ AcpiOsPrintf ("%*s", ((Display * 2) + 1), " "); j += Display; continue; } switch (Display) { case DB_BYTE_DISPLAY: default: /* Default is BYTE display */ AcpiOsPrintf ("%02X ", Buffer[(ACPI_SIZE) i + j]); break; case DB_WORD_DISPLAY: ACPI_MOVE_16_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); AcpiOsPrintf ("%04X ", Temp32); break; case DB_DWORD_DISPLAY: ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); AcpiOsPrintf ("%08X ", Temp32); break; case DB_QWORD_DISPLAY: ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); AcpiOsPrintf ("%08X", Temp32); ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j + 4]); AcpiOsPrintf ("%08X ", Temp32); break; } j += Display; } /* * Print the ASCII equivalent characters but watch out for the bad * unprintable ones (printable chars are 0x20 through 0x7E) */ AcpiOsPrintf (" "); for (j = 0; j < 16; j++) { if (i + j >= Count) { AcpiOsPrintf ("\n"); return; } BufChar = Buffer[(ACPI_SIZE) i + j]; if (ACPI_IS_PRINT (BufChar)) { AcpiOsPrintf ("%c", BufChar); } else { AcpiOsPrintf ("."); } } /* Done with that line. */ AcpiOsPrintf ("\n"); i += 16; } return; }
union acpi_parse_object * acpi_ps_get_next_field ( struct acpi_parse_state *parser_state) { u32 aml_offset = (u32) ACPI_PTR_DIFF (parser_state->aml, parser_state->aml_start); union acpi_parse_object *field; u16 opcode; u32 name; ACPI_FUNCTION_TRACE ("ps_get_next_field"); /* determine field type */ switch (ACPI_GET8 (parser_state->aml)) { default: opcode = AML_INT_NAMEDFIELD_OP; break; case 0x00: opcode = AML_INT_RESERVEDFIELD_OP; parser_state->aml++; break; case 0x01: opcode = AML_INT_ACCESSFIELD_OP; parser_state->aml++; break; } /* Allocate a new field op */ field = acpi_ps_alloc_op (opcode); if (!field) { return_PTR (NULL); } field->common.aml_offset = aml_offset; /* Decode the field type */ switch (opcode) { case AML_INT_NAMEDFIELD_OP: /* Get the 4-character name */ ACPI_MOVE_32_TO_32 (&name, parser_state->aml); acpi_ps_set_name (field, name); parser_state->aml += ACPI_NAME_SIZE; /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length (parser_state); break; case AML_INT_RESERVEDFIELD_OP: /* Get the length which is encoded as a package length */ field->common.value.size = acpi_ps_get_next_package_length (parser_state); break; case AML_INT_ACCESSFIELD_OP: /* * Get access_type and access_attrib and merge into the field Op * access_type is first operand, access_attribute is second */ field->common.value.integer = (ACPI_GET8 (parser_state->aml) << 8); parser_state->aml++; field->common.value.integer |= ACPI_GET8 (parser_state->aml); parser_state->aml++; break; default: /* Opcode was set in previous switch */ break; } return_PTR (field); }
acpi_status acpi_ns_lookup(union acpi_generic_state *scope_info, char *pathname, acpi_object_type type, acpi_interpreter_mode interpreter_mode, u32 flags, struct acpi_walk_state *walk_state, struct acpi_namespace_node **return_node) { acpi_status status; char *path = pathname; struct acpi_namespace_node *prefix_node; struct acpi_namespace_node *current_node = NULL; struct acpi_namespace_node *this_node = NULL; u32 num_segments; u32 num_carats; acpi_name simple_name; acpi_object_type type_to_check_for; acpi_object_type this_search_type; u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; u32 local_flags; ACPI_FUNCTION_TRACE(ns_lookup); if (!return_node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); *return_node = ACPI_ENTRY_NOT_FOUND; acpi_gbl_ns_lookup_count++; if (!acpi_gbl_root_node) { return_ACPI_STATUS(AE_NO_NAMESPACE); } if ((!scope_info) || (!scope_info->scope.node)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", acpi_gbl_root_node)); prefix_node = acpi_gbl_root_node; } else { prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]", prefix_node, acpi_ut_get_descriptor_name(prefix_node))); return_ACPI_STATUS(AE_AML_INTERNAL); } if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { while (!acpi_ns_opens_scope(prefix_node->type) && prefix_node->type != ACPI_TYPE_ANY) { prefix_node = acpi_ns_get_parent_node(prefix_node); } } } type_to_check_for = type; if (!pathname) { num_segments = 0; this_node = acpi_gbl_root_node; path = ""; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null Pathname (Zero segments), Flags=%X\n", flags)); } else { if (*path == (u8) AML_ROOT_PREFIX) { this_node = acpi_gbl_root_node; search_parent_flag = ACPI_NS_NO_UPSEARCH; path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Path is absolute from root [%p]\n", this_node)); } else { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", acpi_ut_get_node_name(prefix_node), prefix_node)); this_node = prefix_node; num_carats = 0; while (*path == (u8) AML_PARENT_PREFIX) { search_parent_flag = ACPI_NS_NO_UPSEARCH; path++; num_carats++; this_node = acpi_ns_get_parent_node(this_node); if (!this_node) { ACPI_ERROR((AE_INFO, "ACPI path has too many parent prefixes (^) " "- reached beyond root node")); return_ACPI_STATUS(AE_NOT_FOUND); } } if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %d carat(s)\n", acpi_ut_get_node_name (this_node), num_carats)); } } switch (*path) { case 0: num_segments = 0; type = this_node->type; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Prefix-only Pathname (Zero name segments), Flags=%X\n", flags)); break; case AML_DUAL_NAME_PREFIX: search_parent_flag = ACPI_NS_NO_UPSEARCH; num_segments = 2; path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Dual Pathname (2 segments, Flags=%X)\n", flags)); break; case AML_MULTI_NAME_PREFIX_OP: search_parent_flag = ACPI_NS_NO_UPSEARCH; path++; num_segments = (u32) (u8) * path; path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Multi Pathname (%d Segments, Flags=%X)\n", num_segments, flags)); break; default: num_segments = 1; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Simple Pathname (1 segment, Flags=%X)\n", flags)); break; } ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path)); } this_search_type = ACPI_TYPE_ANY; current_node = this_node; while (num_segments && current_node) { num_segments--; if (!num_segments) { this_search_type = type; if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) && (flags & ACPI_NS_SEARCH_PARENT)) { local_flags |= ACPI_NS_SEARCH_PARENT; } if (flags & ACPI_NS_ERROR_IF_FOUND) { local_flags |= ACPI_NS_ERROR_IF_FOUND; } } ACPI_MOVE_32_TO_32(&simple_name, path); status = acpi_ns_search_and_enter(simple_name, walk_state, current_node, interpreter_mode, this_search_type, local_flags, &this_node); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] not found in scope [%4.4s] %p\n", (char *)&simple_name, (char *)¤t_node->name, current_node)); } *return_node = this_node; return_ACPI_STATUS(status); } if (num_segments > 0) { if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { if (!this_node->object) { return_ACPI_STATUS(AE_NOT_EXIST); } if (acpi_ns_opens_scope (((struct acpi_namespace_node *) this_node->object)->type)) { this_node = (struct acpi_namespace_node *) this_node->object; } } } else { if ((type_to_check_for != ACPI_TYPE_ANY) && (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && (this_node->type != ACPI_TYPE_ANY) && (this_node->type != type_to_check_for)) { ACPI_WARNING((AE_INFO, "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR(char, &simple_name), acpi_ut_get_type_name(this_node-> type), acpi_ut_get_type_name (type_to_check_for))); } if (type == ACPI_TYPE_ANY) { type = this_node->type; } } path += ACPI_NAME_SIZE; current_node = this_node; }
ACPI_STATUS AcpiNsLookup ( ACPI_GENERIC_STATE *ScopeInfo, char *Pathname, ACPI_OBJECT_TYPE Type, ACPI_INTERPRETER_MODE InterpreterMode, UINT32 Flags, ACPI_WALK_STATE *WalkState, ACPI_NAMESPACE_NODE **ReturnNode) { ACPI_STATUS Status; char *Path = Pathname; ACPI_NAMESPACE_NODE *PrefixNode; ACPI_NAMESPACE_NODE *CurrentNode = NULL; ACPI_NAMESPACE_NODE *ThisNode = NULL; UINT32 NumSegments; UINT32 NumCarats; ACPI_NAME SimpleName; ACPI_OBJECT_TYPE TypeToCheckFor; ACPI_OBJECT_TYPE ThisSearchType; UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; UINT32 LocalFlags; ACPI_FUNCTION_TRACE (NsLookup); if (!ReturnNode) { return_ACPI_STATUS (AE_BAD_PARAMETER); } LocalFlags = Flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_SEARCH_PARENT); *ReturnNode = ACPI_ENTRY_NOT_FOUND; AcpiGbl_NsLookupCount++; if (!AcpiGbl_RootNode) { return_ACPI_STATUS (AE_NO_NAMESPACE); } /* Get the prefix scope. A null scope means use the root scope */ if ((!ScopeInfo) || (!ScopeInfo->Scope.Node)) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", AcpiGbl_RootNode)); PrefixNode = AcpiGbl_RootNode; } else { PrefixNode = ScopeInfo->Scope.Node; if (ACPI_GET_DESCRIPTOR_TYPE (PrefixNode) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR ((AE_INFO, "%p is not a namespace node [%s]", PrefixNode, AcpiUtGetDescriptorName (PrefixNode))); return_ACPI_STATUS (AE_AML_INTERNAL); } if (!(Flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a * Device/Method, etc.) It could be a Package or other object * node. Backup up the tree to find the containing scope node. */ while (!AcpiNsOpensScope (PrefixNode->Type) && PrefixNode->Type != ACPI_TYPE_ANY) { PrefixNode = PrefixNode->Parent; } } } /* Save type. TBD: may be no longer necessary */ TypeToCheckFor = Type; /* * Begin examination of the actual pathname */ if (!Pathname) { /* A Null NamePath is allowed and refers to the root */ NumSegments = 0; ThisNode = AcpiGbl_RootNode; Path = ""; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Null Pathname (Zero segments), Flags=%X\n", Flags)); } else { /* * Name pointer is valid (and must be in internal name format) * * Check for scope prefixes: * * As represented in the AML stream, a namepath consists of an * optional scope prefix followed by a name segment part. * * If present, the scope prefix is either a Root Prefix (in * which case the name is fully qualified), or one or more * Parent Prefixes (in which case the name's scope is relative * to the current scope). */ if (*Path == (UINT8) AML_ROOT_PREFIX) { /* Pathname is fully qualified, start from the root */ ThisNode = AcpiGbl_RootNode; SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Point to name segment part */ Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Path is absolute from root [%p]\n", ThisNode)); } else { /* Pathname is relative to current scope, start there */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", AcpiUtGetNodeName (PrefixNode), PrefixNode)); /* * Handle multiple Parent Prefixes (carat) by just getting * the parent node for each prefix instance. */ ThisNode = PrefixNode; NumCarats = 0; while (*Path == (UINT8) AML_PARENT_PREFIX) { /* Name is fully qualified, no search rules apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* * Point past this prefix to the name segment * part or the next Parent Prefix */ Path++; /* Backup to the parent node */ NumCarats++; ThisNode = ThisNode->Parent; if (!ThisNode) { /* Current scope has no parent scope */ ACPI_ERROR ((AE_INFO, "%s: Path has too many parent prefixes (^) " "- reached beyond root node", Pathname)); return_ACPI_STATUS (AE_NOT_FOUND); } } if (SearchParentFlag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %u carat(s)\n", AcpiUtGetNodeName (ThisNode), NumCarats)); } } /* * Determine the number of ACPI name segments in this pathname. * * The segment part consists of either: * - A Null name segment (0) * - A DualNamePrefix followed by two 4-byte name segments * - A MultiNamePrefix followed by a byte indicating the * number of segments and the segments themselves. * - A single 4-byte name segment * * Examine the name prefix opcode, if any, to determine the number of * segments. */ switch (*Path) { case 0: /* * Null name after a root or parent prefixes. We already * have the correct target node and there are no name segments. */ NumSegments = 0; Type = ThisNode->Type; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Prefix-only Pathname (Zero name segments), Flags=%X\n", Flags)); break; case AML_DUAL_NAME_PREFIX: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Two segments, point to first name segment */ NumSegments = 2; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Dual Pathname (2 segments, Flags=%X)\n", Flags)); break; case AML_MULTI_NAME_PREFIX_OP: /* More than one NameSeg, search rules do not apply */ SearchParentFlag = ACPI_NS_NO_UPSEARCH; /* Extract segment count, point to first name segment */ Path++; NumSegments = (UINT32) (UINT8) *Path; Path++; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Multi Pathname (%u Segments, Flags=%X)\n", NumSegments, Flags)); break; default: /* * Not a Null name, no Dual or Multi prefix, hence there is * only one name segment and Pathname is already pointing to it. */ NumSegments = 1; ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Simple Pathname (1 segment, Flags=%X)\n", Flags)); break; } ACPI_DEBUG_EXEC (AcpiNsPrintPathname (NumSegments, Path)); } /* * Search namespace for each segment of the name. Loop through and * verify (or add to the namespace) each name segment. * * The object type is significant only at the last name * segment. (We don't care about the types along the path, only * the type of the final target object.) */ ThisSearchType = ACPI_TYPE_ANY; CurrentNode = ThisNode; while (NumSegments && CurrentNode) { NumSegments--; if (!NumSegments) { /* This is the last segment, enable typechecking */ ThisSearchType = Type; /* * Only allow automatic parent search (search rules) if the caller * requested it AND we have a single, non-fully-qualified NameSeg */ if ((SearchParentFlag != ACPI_NS_NO_UPSEARCH) && (Flags & ACPI_NS_SEARCH_PARENT)) { LocalFlags |= ACPI_NS_SEARCH_PARENT; } /* Set error flag according to caller */ if (Flags & ACPI_NS_ERROR_IF_FOUND) { LocalFlags |= ACPI_NS_ERROR_IF_FOUND; } } /* Extract one ACPI name from the front of the pathname */ ACPI_MOVE_32_TO_32 (&SimpleName, Path); /* Try to find the single (4 character) ACPI name */ Status = AcpiNsSearchAndEnter (SimpleName, WalkState, CurrentNode, InterpreterMode, ThisSearchType, LocalFlags, &ThisNode); if (ACPI_FAILURE (Status)) { if (Status == AE_NOT_FOUND) { /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Name [%4.4s] not found in scope [%4.4s] %p\n", (char *) &SimpleName, (char *) &CurrentNode->Name, CurrentNode)); } *ReturnNode = ThisNode; return_ACPI_STATUS (Status); } /* More segments to follow? */ if (NumSegments > 0) { /* * If we have an alias to an object that opens a scope (such as a * device or processor), we need to dereference the alias here so * that we can access any children of the original node (via the * remaining segments). */ if (ThisNode->Type == ACPI_TYPE_LOCAL_ALIAS) { if (!ThisNode->Object) { return_ACPI_STATUS (AE_NOT_EXIST); } if (AcpiNsOpensScope (((ACPI_NAMESPACE_NODE *) ThisNode->Object)->Type)) { ThisNode = (ACPI_NAMESPACE_NODE *) ThisNode->Object; } } } /* Special handling for the last segment (NumSegments == 0) */ else { /* * Sanity typecheck of the target object: * * If 1) This is the last segment (NumSegments == 0) * 2) And we are looking for a specific type * (Not checking for TYPE_ANY) * 3) Which is not an alias * 4) Which is not a local type (TYPE_SCOPE) * 5) And the type of target object is known (not TYPE_ANY) * 6) And target object does not match what we are looking for * * Then we have a type mismatch. Just warn and ignore it. */ if ((TypeToCheckFor != ACPI_TYPE_ANY) && (TypeToCheckFor != ACPI_TYPE_LOCAL_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (TypeToCheckFor != ACPI_TYPE_LOCAL_SCOPE) && (ThisNode->Type != ACPI_TYPE_ANY) && (ThisNode->Type != TypeToCheckFor)) { /* Complain about a type mismatch */ ACPI_WARNING ((AE_INFO, "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR (char, &SimpleName), AcpiUtGetTypeName (ThisNode->Type), AcpiUtGetTypeName (TypeToCheckFor))); } /* * If this is the last name segment and we are not looking for a * specific type, but the type of found object is known, use that * type to (later) see if it opens a scope. */ if (Type == ACPI_TYPE_ANY) { Type = ThisNode->Type; } } /* Point to next name segment and make this node current */ Path += ACPI_NAME_SIZE; CurrentNode = ThisNode; }
acpi_status acpi_rs_memory32_range_resource ( u8 *byte_stream_buffer, acpi_size *bytes_consumed, u8 **output_buffer, acpi_size *structure_size) { u8 *buffer = byte_stream_buffer; struct acpi_resource *output_struct = (void *) *output_buffer; u16 temp16 = 0; u8 temp8 = 0; acpi_size struct_size = ACPI_SIZEOF_RESOURCE (struct acpi_resource_mem32); ACPI_FUNCTION_TRACE ("rs_memory32_range_resource"); /* * Point past the Descriptor to get the number of bytes consumed */ buffer += 1; ACPI_MOVE_16_TO_16 (&temp16, buffer); buffer += 2; *bytes_consumed = (acpi_size) temp16 + 3; output_struct->id = ACPI_RSTYPE_MEM32; /* * Point to the place in the output buffer where the data portion will * begin. * 1. Set the RESOURCE_DATA * Data to point to its own address, then * 2. Set the pointer to the next address. * * NOTE: output_struct->Data is cast to u8, otherwise, this addition adds * 4 * sizeof(RESOURCE_DATA) instead of 4 * sizeof(u8) */ /* * Check Byte 3 the Read/Write bit */ temp8 = *buffer; buffer += 1; output_struct->data.memory32.read_write_attribute = temp8 & 0x01; /* * Get min_base_address (Bytes 4-7) */ ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.min_base_address, buffer); buffer += 4; /* * Get max_base_address (Bytes 8-11) */ ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.max_base_address, buffer); buffer += 4; /* * Get Alignment (Bytes 12-15) */ ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.alignment, buffer); buffer += 4; /* * Get range_length (Bytes 16-19) */ ACPI_MOVE_32_TO_32 (&output_struct->data.memory32.range_length, buffer); /* * Set the Length parameter */ output_struct->length = (u32) struct_size; /* * Return the final size of the structure */ *structure_size = struct_size; return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AdGetLocalTables ( char *Filename, BOOLEAN GetAllTables) { ACPI_STATUS Status; ACPI_TABLE_HEADER TableHeader; ACPI_TABLE_HEADER *NewTable; UINT32 NumTables; UINT32 PointerSize; UINT32 TableIndex; if (GetAllTables) { ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_RSDT); AcpiOsTableOverride (&TableHeader, &NewTable); if (!NewTable) { fprintf (stderr, "Could not obtain RSDT\n"); return AE_NO_ACPI_TABLES; } else { AdWriteTable (NewTable, NewTable->Length, ACPI_SIG_RSDT, NewTable->OemTableId); } if (ACPI_COMPARE_NAME (NewTable->Signature, ACPI_SIG_RSDT)) { PointerSize = sizeof (UINT32); } else { PointerSize = sizeof (UINT64); } /* * Determine the number of tables pointed to by the RSDT/XSDT. * This is defined by the ACPI Specification to be the number of * pointers contained within the RSDT/XSDT. The size of the pointers * is architecture-dependent. */ NumTables = (NewTable->Length - sizeof (ACPI_TABLE_HEADER)) / PointerSize; AcpiOsPrintf ("There are %u tables defined in the %4.4s\n\n", NumTables, NewTable->Signature); /* Get the FADT */ ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_FADT); AcpiOsTableOverride (&TableHeader, &NewTable); if (NewTable) { AdWriteTable (NewTable, NewTable->Length, ACPI_SIG_FADT, NewTable->OemTableId); } AcpiOsPrintf ("\n"); /* Don't bother with FACS, it is usually all zeros */ } /* Always get the DSDT */ ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_DSDT); AcpiOsTableOverride (&TableHeader, &NewTable); if (NewTable) { AdWriteTable (NewTable, NewTable->Length, ACPI_SIG_DSDT, NewTable->OemTableId); /* Store DSDT in the Table Manager */ Status = AcpiTbStoreTable (0, NewTable, NewTable->Length, 0, &TableIndex); if (ACPI_FAILURE (Status)) { fprintf (stderr, "Could not store DSDT\n"); return AE_NO_ACPI_TABLES; } } else { fprintf (stderr, "Could not obtain DSDT\n"); return AE_NO_ACPI_TABLES; } #if 0 /* TBD: Future implementation */ AcpiOsPrintf ("\n"); /* Get all SSDTs */ ACPI_MOVE_32_TO_32 (TableHeader.Signature, ACPI_SIG_SSDT); do { NewTable = NULL; Status = AcpiOsTableOverride (&TableHeader, &NewTable); } while (NewTable); #endif return AE_OK; }
UINT8 * AcpiDbEncodePldBuffer ( ACPI_PLD_INFO *PldInfo) { UINT32 *Buffer; UINT32 Dword; Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE); if (!Buffer) { return (NULL); } /* First 32 bits */ Dword = 0; ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision); ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor); ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color); ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword); /* Second 32 bits */ Dword = 0; ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width); ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height); ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword); /* Third 32 bits */ Dword = 0; ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible); ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock); ACPI_PLD_SET_LID (&Dword, PldInfo->Lid); ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel); ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition); ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition); ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape); ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation); ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken); ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition); ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay); ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword); /* Fourth 32 bits */ Dword = 0; ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable); ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired); ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber); ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber); ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference); ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation); ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order); ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword); if (PldInfo->Revision >= 2) { /* Fifth 32 bits */ Dword = 0; ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset); ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset); ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword); } return (ACPI_CAST_PTR (UINT8, Buffer)); }
void AcpiRsMoveData ( void *Destination, void *Source, UINT16 ItemCount, UINT8 MoveType) { UINT32 i; ACPI_FUNCTION_ENTRY (); /* One move per item */ for (i = 0; i < ItemCount; i++) { switch (MoveType) { /* * For the 8-bit case, we can perform the move all at once * since there are no alignment or endian issues */ case ACPI_RSC_MOVE8: case ACPI_RSC_MOVE_GPIO_RES: case ACPI_RSC_MOVE_SERIAL_VEN: case ACPI_RSC_MOVE_SERIAL_RES: memcpy (Destination, Source, ItemCount); return; /* * 16-, 32-, and 64-bit cases must use the move macros that perform * endian conversion and/or accommodate hardware that cannot perform * misaligned memory transfers */ case ACPI_RSC_MOVE16: case ACPI_RSC_MOVE_GPIO_PIN: ACPI_MOVE_16_TO_16 ( &ACPI_CAST_PTR (UINT16, Destination)[i], &ACPI_CAST_PTR (UINT16, Source)[i]); break; case ACPI_RSC_MOVE32: ACPI_MOVE_32_TO_32 ( &ACPI_CAST_PTR (UINT32, Destination)[i], &ACPI_CAST_PTR (UINT32, Source)[i]); break; case ACPI_RSC_MOVE64: ACPI_MOVE_64_TO_64 ( &ACPI_CAST_PTR (UINT64, Destination)[i], &ACPI_CAST_PTR (UINT64, Source)[i]); break; default: return; } } }
u8 *acpi_db_encode_pld_buffer(struct acpi_pld_info *pld_info) { u32 *buffer; u32 dword; buffer = ACPI_ALLOCATE_ZEROED(ACPI_PLD_BUFFER_SIZE); if (!buffer) { return (NULL); } /* First 32 bits */ dword = 0; ACPI_PLD_SET_REVISION(&dword, pld_info->revision); ACPI_PLD_SET_IGNORE_COLOR(&dword, pld_info->ignore_color); ACPI_PLD_SET_RED(&dword, pld_info->red); ACPI_PLD_SET_GREEN(&dword, pld_info->green); ACPI_PLD_SET_BLUE(&dword, pld_info->blue); ACPI_MOVE_32_TO_32(&buffer[0], &dword); /* Second 32 bits */ dword = 0; ACPI_PLD_SET_WIDTH(&dword, pld_info->width); ACPI_PLD_SET_HEIGHT(&dword, pld_info->height); ACPI_MOVE_32_TO_32(&buffer[1], &dword); /* Third 32 bits */ dword = 0; ACPI_PLD_SET_USER_VISIBLE(&dword, pld_info->user_visible); ACPI_PLD_SET_DOCK(&dword, pld_info->dock); ACPI_PLD_SET_LID(&dword, pld_info->lid); ACPI_PLD_SET_PANEL(&dword, pld_info->panel); ACPI_PLD_SET_VERTICAL(&dword, pld_info->vertical_position); ACPI_PLD_SET_HORIZONTAL(&dword, pld_info->horizontal_position); ACPI_PLD_SET_SHAPE(&dword, pld_info->shape); ACPI_PLD_SET_ORIENTATION(&dword, pld_info->group_orientation); ACPI_PLD_SET_TOKEN(&dword, pld_info->group_token); ACPI_PLD_SET_POSITION(&dword, pld_info->group_position); ACPI_PLD_SET_BAY(&dword, pld_info->bay); ACPI_MOVE_32_TO_32(&buffer[2], &dword); /* Fourth 32 bits */ dword = 0; ACPI_PLD_SET_EJECTABLE(&dword, pld_info->ejectable); ACPI_PLD_SET_OSPM_EJECT(&dword, pld_info->ospm_eject_required); ACPI_PLD_SET_CABINET(&dword, pld_info->cabinet_number); ACPI_PLD_SET_CARD_CAGE(&dword, pld_info->card_cage_number); ACPI_PLD_SET_REFERENCE(&dword, pld_info->reference); ACPI_PLD_SET_ROTATION(&dword, pld_info->rotation); ACPI_PLD_SET_ORDER(&dword, pld_info->order); ACPI_MOVE_32_TO_32(&buffer[3], &dword); if (pld_info->revision >= 2) { /* Fifth 32 bits */ dword = 0; ACPI_PLD_SET_VERT_OFFSET(&dword, pld_info->vertical_offset); ACPI_PLD_SET_HORIZ_OFFSET(&dword, pld_info->horizontal_offset); ACPI_MOVE_32_TO_32(&buffer[4], &dword); } return (ACPI_CAST_PTR(u8, buffer)); }
void ApCheckForGpeNameConflict ( ACPI_PARSE_OBJECT *Op) { ACPI_PARSE_OBJECT *NextOp; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; char Target[ACPI_NAME_SIZE]; /* Need a null-terminated string version of NameSeg */ ACPI_MOVE_32_TO_32 (Name, &Op->Asl.NameSeg); Name[ACPI_NAME_SIZE] = 0; /* * For a GPE method: * 1st char must be underscore * 2nd char must be L or E * 3rd/4th chars must be a hex number */ if ((Name[0] != '_') || ((Name[1] != 'L') && (Name[1] != 'E'))) { return; } /* Verify 3rd/4th chars are a valid hex value */ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) { return; } /* * We are now sure we have an _Lxx or _Exx. * Create the target name that would cause collision (Flip E/L) */ ACPI_MOVE_32_TO_32 (Target, Name); /* Inject opposite letter ("L" versus "E") */ if (Name[1] == 'L') { Target[1] = 'E'; } else /* Name[1] == 'E' */ { Target[1] = 'L'; } /* Search all peers (objects within this scope) for target match */ NextOp = Op->Asl.Next; while (NextOp) { /* * We mostly care about methods, but check Name() constructs also, * even though they will get another error for not being a method. * All GPE names must be defined as control methods. */ if ((NextOp->Asl.ParseOpcode == PARSEOP_METHOD) || (NextOp->Asl.ParseOpcode == PARSEOP_NAME)) { if (ACPI_COMPARE_NAME (Target, NextOp->Asl.NameSeg)) { /* Found both _Exy and _Lxy in the same scope, error */ AslError (ASL_ERROR, ASL_MSG_GPE_NAME_CONFLICT, NextOp, Name); return; } } NextOp = NextOp->Asl.Next; } /* OK, no conflict found */ return; }
ACPI_STATUS AcpiEvMatchGpeMethod ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); ACPI_GPE_EVENT_INFO *GpeEventInfo; ACPI_NAMESPACE_NODE *GpeDevice; ACPI_STATUS Status; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; UINT8 Type; ACPI_FUNCTION_TRACE (EvMatchGpeMethod); /* Check if requested OwnerId matches this OwnerId */ if ((WalkInfo->ExecuteByOwnerId) && (MethodNode->OwnerId != WalkInfo->OwnerId)) { return_ACPI_STATUS (AE_OK); } /* * Match and decode the _Lxx and _Exx GPE method names * * 1) Extract the method name and null terminate it */ ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); Name[ACPI_NAME_SIZE] = 0; /* 2) Name must begin with an underscore */ if (Name[0] != '_') { return_ACPI_STATUS (AE_OK); /* Ignore this method */ } /* * 3) Edge/Level determination is based on the 2nd character * of the method name * * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. */ switch (Name[1]) { case 'L': Type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': Type = ACPI_GPE_EDGE_TRIGGERED; break; default: /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Ignoring unknown GPE method type: %s " "(name not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* 4) The last two characters of the name are the hex GPE Number */ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Could not extract GPE number from name: %s " "(name is not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); if (!GpeEventInfo) { /* * This GpeNumber is not valid for this GPE block, just ignore it. * However, it may be valid for a different GPE block, since GPE0 * and GPE1 methods both appear under \_GPE. */ return_ACPI_STATUS (AE_OK); } if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { /* If there is already a handler, ignore this GPE method */ return_ACPI_STATUS (AE_OK); } if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { /* * If there is already a method, ignore this method. But check * for a type mismatch (if both the _Lxx AND _Exx exist) */ if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) { ACPI_ERROR ((AE_INFO, "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", GpeNumber, GpeNumber, GpeNumber)); } return_ACPI_STATUS (AE_OK); } /* * Add the GPE information from above to the GpeEventInfo block for * use during dispatch of this GPE. */ GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); GpeEventInfo->Dispatch.MethodNode = MethodNode; /* * Enable this GPE if requested. This only happens when during the * execution of a Load or LoadTable operator. We have found a new * GPE method and want to immediately enable the GPE if it is a * runtime GPE. */ if (WalkInfo->EnableThisGpe) { /* Ignore GPEs that can wake the system */ if (!(GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE) || !AcpiGbl_LeaveWakeGpesDisabled) { WalkInfo->Count++; GpeDevice = WalkInfo->GpeDevice; if (GpeDevice == AcpiGbl_FadtGpeDevice) { GpeDevice = NULL; } Status = AcpiEnableGpe (GpeDevice, GpeNumber, ACPI_GPE_TYPE_RUNTIME); if (ACPI_FAILURE (Status)) { ACPI_EXCEPTION ((AE_INFO, Status, "Could not enable GPE 0x%02X", GpeNumber)); } } } ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", Name, GpeNumber)); return_ACPI_STATUS (AE_OK); }
acpi_status acpi_rs_memory32_range_stream ( struct acpi_resource *linked_list, u8 **output_buffer, acpi_size *bytes_consumed) { u8 *buffer = *output_buffer; u16 temp16 = 0; u8 temp8 = 0; ACPI_FUNCTION_TRACE ("rs_memory32_range_stream"); /* * The descriptor field is static */ *buffer = 0x85; buffer += 1; /* * The length field is static */ temp16 = 0x11; ACPI_MOVE_16_TO_16 (buffer, &temp16); buffer += 2; /* * Set the Information Byte */ temp8 = (u8) (linked_list->data.memory32.read_write_attribute & 0x01); *buffer = temp8; buffer += 1; /* * Set the Range minimum base address */ ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.min_base_address); buffer += 4; /* * Set the Range maximum base address */ ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.max_base_address); buffer += 4; /* * Set the base alignment */ ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.alignment); buffer += 4; /* * Set the range length */ ACPI_MOVE_32_TO_32 (buffer, &linked_list->data.memory32.range_length); buffer += 4; /* * Return the number of bytes consumed in this operation */ *bytes_consumed = ACPI_PTR_DIFF (buffer, *output_buffer); return_ACPI_STATUS (AE_OK); }
ACPI_STATUS AcpiDecodePldBuffer ( UINT8 *InBuffer, ACPI_SIZE Length, ACPI_PLD_INFO **ReturnBuffer) { ACPI_PLD_INFO *PldInfo; UINT32 *Buffer = ACPI_CAST_PTR (UINT32, InBuffer); UINT32 Dword; /* Parameter validation */ if (!InBuffer || !ReturnBuffer || (Length < 16)) { return (AE_BAD_PARAMETER); } PldInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PLD_INFO)); if (!PldInfo) { return (AE_NO_MEMORY); } /* First 32-bit DWord */ ACPI_MOVE_32_TO_32 (&Dword, &Buffer[0]); PldInfo->Revision = ACPI_PLD_GET_REVISION (&Dword); PldInfo->IgnoreColor = ACPI_PLD_GET_IGNORE_COLOR (&Dword); PldInfo->Color = ACPI_PLD_GET_COLOR (&Dword); /* Second 32-bit DWord */ ACPI_MOVE_32_TO_32 (&Dword, &Buffer[1]); PldInfo->Width = ACPI_PLD_GET_WIDTH (&Dword); PldInfo->Height = ACPI_PLD_GET_HEIGHT(&Dword); /* Third 32-bit DWord */ ACPI_MOVE_32_TO_32 (&Dword, &Buffer[2]); PldInfo->UserVisible = ACPI_PLD_GET_USER_VISIBLE (&Dword); PldInfo->Dock = ACPI_PLD_GET_DOCK (&Dword); PldInfo->Lid = ACPI_PLD_GET_LID (&Dword); PldInfo->Panel = ACPI_PLD_GET_PANEL (&Dword); PldInfo->VerticalPosition = ACPI_PLD_GET_VERTICAL (&Dword); PldInfo->HorizontalPosition = ACPI_PLD_GET_HORIZONTAL (&Dword); PldInfo->Shape = ACPI_PLD_GET_SHAPE (&Dword); PldInfo->GroupOrientation = ACPI_PLD_GET_ORIENTATION (&Dword); PldInfo->GroupToken = ACPI_PLD_GET_TOKEN (&Dword); PldInfo->GroupPosition = ACPI_PLD_GET_POSITION (&Dword); PldInfo->Bay = ACPI_PLD_GET_BAY (&Dword); /* Fourth 32-bit DWord */ ACPI_MOVE_32_TO_32 (&Dword, &Buffer[3]); PldInfo->Ejectable = ACPI_PLD_GET_EJECTABLE (&Dword); PldInfo->OspmEjectRequired = ACPI_PLD_GET_OSPM_EJECT (&Dword); PldInfo->CabinetNumber = ACPI_PLD_GET_CABINET (&Dword); PldInfo->CardCageNumber = ACPI_PLD_GET_CARD_CAGE (&Dword); PldInfo->Reference = ACPI_PLD_GET_REFERENCE (&Dword); PldInfo->Rotation = ACPI_PLD_GET_ROTATION (&Dword); PldInfo->Order = ACPI_PLD_GET_ORDER (&Dword); if (Length >= ACPI_PLD_BUFFER_SIZE) { /* Fifth 32-bit DWord (Revision 2 of _PLD) */ ACPI_MOVE_32_TO_32 (&Dword, &Buffer[4]); PldInfo->VerticalOffset = ACPI_PLD_GET_VERT_OFFSET (&Dword); PldInfo->HorizontalOffset = ACPI_PLD_GET_HORIZ_OFFSET (&Dword); } *ReturnBuffer = PldInfo; return (AE_OK); }
static acpi_status acpi_ev_save_method_info(acpi_handle obj_handle, u32 level, void *obj_desc, void **return_value) { struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; struct acpi_gpe_event_info *gpe_event_info; u32 gpe_number; char name[ACPI_NAME_SIZE + 1]; u8 type; acpi_status status; ACPI_FUNCTION_TRACE("ev_save_method_info"); /* * _Lxx and _Exx GPE method support * * 1) Extract the name from the object and convert to a string */ ACPI_MOVE_32_TO_32(name, &((struct acpi_namespace_node *)obj_handle)->name. integer); name[ACPI_NAME_SIZE] = 0; /* * 2) Edge/Level determination is based on the 2nd character * of the method name * * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE * if a _PRW object is found that points to this GPE. */ switch (name[1]) { case 'L': type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': type = ACPI_GPE_EDGE_TRIGGERED; break; default: /* Unknown method type, just ignore it! */ ACPI_ERROR((AE_INFO, "Unknown GPE method type: %s (name not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* Convert the last two characters of the name to the GPE Number */ gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); if (gpe_number == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ ACPI_ERROR((AE_INFO, "Could not extract GPE number from name: %s (name is not of form _Lxx or _Exx)", name)); return_ACPI_STATUS(AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ if ((gpe_number < gpe_block->block_base_number) || (gpe_number >= (gpe_block->block_base_number + (gpe_block->register_count * 8)))) { /* * Not valid for this GPE block, just ignore it * However, it may be valid for a different GPE block, since GPE0 and GPE1 * methods both appear under \_GPE. */ return_ACPI_STATUS(AE_OK); } /* * Now we can add this information to the gpe_event_info block * for use during dispatch of this GPE. Default type is RUNTIME, although * this may change when the _PRW methods are executed later. */ gpe_event_info = &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD | ACPI_GPE_TYPE_RUNTIME); gpe_event_info->dispatch.method_node = (struct acpi_namespace_node *)obj_handle; /* Update enable mask, but don't enable the HW GPE as of yet */ status = acpi_ev_enable_gpe(gpe_event_info, FALSE); ACPI_DEBUG_PRINT((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", name, gpe_number)); return_ACPI_STATUS(status); }
UINT32 AcpiNsBuildNormalizedPath ( ACPI_NAMESPACE_NODE *Node, char *FullPath, UINT32 PathSize, BOOLEAN NoTrailing) { UINT32 Length = 0, i; char Name[ACPI_NAME_SIZE]; BOOLEAN DoNoTrailing; char c, *Left, *Right; ACPI_NAMESPACE_NODE *NextNode; ACPI_FUNCTION_TRACE_PTR (NsBuildNormalizedPath, Node); #define ACPI_PATH_PUT8(Path, Size, Byte, Length) \ do { \ if ((Length) < (Size)) \ { \ (Path)[(Length)] = (Byte); \ } \ (Length)++; \ } while (0) /* * Make sure the PathSize is correct, so that we don't need to * validate both FullPath and PathSize. */ if (!FullPath) { PathSize = 0; } if (!Node) { goto BuildTrailingNull; } NextNode = Node; while (NextNode && NextNode != AcpiGbl_RootNode) { if (NextNode != Node) { ACPI_PATH_PUT8(FullPath, PathSize, AML_DUAL_NAME_PREFIX, Length); } ACPI_MOVE_32_TO_32 (Name, &NextNode->Name); DoNoTrailing = NoTrailing; for (i = 0; i < 4; i++) { c = Name[4-i-1]; if (DoNoTrailing && c != '_') { DoNoTrailing = FALSE; } if (!DoNoTrailing) { ACPI_PATH_PUT8(FullPath, PathSize, c, Length); } } NextNode = NextNode->Parent; } ACPI_PATH_PUT8(FullPath, PathSize, AML_ROOT_PREFIX, Length); /* Reverse the path string */ if (Length <= PathSize) { Left = FullPath; Right = FullPath+Length - 1; while (Left < Right) { c = *Left; *Left++ = *Right; *Right-- = c; } } /* Append the trailing null */ BuildTrailingNull: ACPI_PATH_PUT8 (FullPath, PathSize, '\0', Length); #undef ACPI_PATH_PUT8 return_UINT32 (Length); }
acpi_status acpi_ns_lookup(union acpi_generic_state *scope_info, char *pathname, acpi_object_type type, acpi_interpreter_mode interpreter_mode, u32 flags, struct acpi_walk_state *walk_state, struct acpi_namespace_node **return_node) { acpi_status status; char *path = pathname; struct acpi_namespace_node *prefix_node; struct acpi_namespace_node *current_node = NULL; struct acpi_namespace_node *this_node = NULL; u32 num_segments; u32 num_carats; acpi_name simple_name; acpi_object_type type_to_check_for; acpi_object_type this_search_type; u32 search_parent_flag = ACPI_NS_SEARCH_PARENT; u32 local_flags; ACPI_FUNCTION_TRACE(ns_lookup); if (!return_node) { return_ACPI_STATUS(AE_BAD_PARAMETER); } local_flags = flags & ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_IF_FOUND | ACPI_NS_SEARCH_PARENT); *return_node = ACPI_ENTRY_NOT_FOUND; acpi_gbl_ns_lookup_count++; if (!acpi_gbl_root_node) { return_ACPI_STATUS(AE_NO_NAMESPACE); } /* Get the prefix scope. A null scope means use the root scope */ if ((!scope_info) || (!scope_info->scope.node)) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null scope prefix, using root node (%p)\n", acpi_gbl_root_node)); prefix_node = acpi_gbl_root_node; } else { prefix_node = scope_info->scope.node; if (ACPI_GET_DESCRIPTOR_TYPE(prefix_node) != ACPI_DESC_TYPE_NAMED) { ACPI_ERROR((AE_INFO, "%p is not a namespace node [%s]", prefix_node, acpi_ut_get_descriptor_name(prefix_node))); return_ACPI_STATUS(AE_AML_INTERNAL); } if (!(flags & ACPI_NS_PREFIX_IS_SCOPE)) { /* * This node might not be a actual "scope" node (such as a * Device/Method, etc.) It could be a Package or other object * node. Backup up the tree to find the containing scope node. */ while (!acpi_ns_opens_scope(prefix_node->type) && prefix_node->type != ACPI_TYPE_ANY) { prefix_node = prefix_node->parent; } } } /* Save type. TBD: may be no longer necessary */ type_to_check_for = type; /* * Begin examination of the actual pathname */ if (!pathname) { /* A Null name_path is allowed and refers to the root */ num_segments = 0; this_node = acpi_gbl_root_node; path = ""; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Null Pathname (Zero segments), Flags=%X\n", flags)); } else { /* * Name pointer is valid (and must be in internal name format) * * Check for scope prefixes: * * As represented in the AML stream, a namepath consists of an * optional scope prefix followed by a name segment part. * * If present, the scope prefix is either a Root Prefix (in * which case the name is fully qualified), or one or more * Parent Prefixes (in which case the name's scope is relative * to the current scope). */ if (*path == (u8) AML_ROOT_PREFIX) { /* Pathname is fully qualified, start from the root */ this_node = acpi_gbl_root_node; search_parent_flag = ACPI_NS_NO_UPSEARCH; /* Point to name segment part */ path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Path is absolute from root [%p]\n", this_node)); } else { /* Pathname is relative to current scope, start there */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Searching relative to prefix scope [%4.4s] (%p)\n", acpi_ut_get_node_name(prefix_node), prefix_node)); /* * Handle multiple Parent Prefixes (carat) by just getting * the parent node for each prefix instance. */ this_node = prefix_node; num_carats = 0; while (*path == (u8) AML_PARENT_PREFIX) { /* Name is fully qualified, no search rules apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; /* * Point past this prefix to the name segment * part or the next Parent Prefix */ path++; /* Backup to the parent node */ num_carats++; this_node = this_node->parent; if (!this_node) { /* Current scope has no parent scope */ ACPI_ERROR((AE_INFO, "%s: Path has too many parent prefixes (^) " "- reached beyond root node", pathname)); return_ACPI_STATUS(AE_NOT_FOUND); } } if (search_parent_flag == ACPI_NS_NO_UPSEARCH) { ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Search scope is [%4.4s], path has %u carat(s)\n", acpi_ut_get_node_name (this_node), num_carats)); } } /* * Determine the number of ACPI name segments in this pathname. * * The segment part consists of either: * - A Null name segment (0) * - A dual_name_prefix followed by two 4-byte name segments * - A multi_name_prefix followed by a byte indicating the * number of segments and the segments themselves. * - A single 4-byte name segment * * Examine the name prefix opcode, if any, to determine the number of * segments. */ switch (*path) { case 0: /* * Null name after a root or parent prefixes. We already * have the correct target node and there are no name segments. */ num_segments = 0; type = this_node->type; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Prefix-only Pathname (Zero name segments), Flags=%X\n", flags)); break; case AML_DUAL_NAME_PREFIX: /* More than one name_seg, search rules do not apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; /* Two segments, point to first name segment */ num_segments = 2; path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Dual Pathname (2 segments, Flags=%X)\n", flags)); break; case AML_MULTI_NAME_PREFIX_OP: /* More than one name_seg, search rules do not apply */ search_parent_flag = ACPI_NS_NO_UPSEARCH; /* Extract segment count, point to first name segment */ path++; num_segments = (u32) (u8) * path; path++; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Multi Pathname (%u Segments, Flags=%X)\n", num_segments, flags)); break; default: /* * Not a Null name, no Dual or Multi prefix, hence there is * only one name segment and Pathname is already pointing to it. */ num_segments = 1; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Simple Pathname (1 segment, Flags=%X)\n", flags)); break; } ACPI_DEBUG_EXEC(acpi_ns_print_pathname(num_segments, path)); } /* * Search namespace for each segment of the name. Loop through and * verify (or add to the namespace) each name segment. * * The object type is significant only at the last name * segment. (We don't care about the types along the path, only * the type of the final target object.) */ this_search_type = ACPI_TYPE_ANY; current_node = this_node; while (num_segments && current_node) { num_segments--; if (!num_segments) { /* This is the last segment, enable typechecking */ this_search_type = type; /* * Only allow automatic parent search (search rules) if the caller * requested it AND we have a single, non-fully-qualified name_seg */ if ((search_parent_flag != ACPI_NS_NO_UPSEARCH) && (flags & ACPI_NS_SEARCH_PARENT)) { local_flags |= ACPI_NS_SEARCH_PARENT; } /* Set error flag according to caller */ if (flags & ACPI_NS_ERROR_IF_FOUND) { local_flags |= ACPI_NS_ERROR_IF_FOUND; } /* Set override flag according to caller */ if (flags & ACPI_NS_OVERRIDE_IF_FOUND) { local_flags |= ACPI_NS_OVERRIDE_IF_FOUND; } } /* Extract one ACPI name from the front of the pathname */ ACPI_MOVE_32_TO_32(&simple_name, path); /* Try to find the single (4 character) ACPI name */ status = acpi_ns_search_and_enter(simple_name, walk_state, current_node, interpreter_mode, this_search_type, local_flags, &this_node); if (ACPI_FAILURE(status)) { if (status == AE_NOT_FOUND) { /* Name not found in ACPI namespace */ ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "Name [%4.4s] not found in scope [%4.4s] %p\n", (char *)&simple_name, (char *)¤t_node->name, current_node)); } *return_node = this_node; return_ACPI_STATUS(status); } /* More segments to follow? */ if (num_segments > 0) { /* * If we have an alias to an object that opens a scope (such as a * device or processor), we need to dereference the alias here so * that we can access any children of the original node (via the * remaining segments). */ if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) { if (!this_node->object) { return_ACPI_STATUS(AE_NOT_EXIST); } if (acpi_ns_opens_scope (((struct acpi_namespace_node *) this_node->object)->type)) { this_node = (struct acpi_namespace_node *) this_node->object; } } } /* Special handling for the last segment (num_segments == 0) */ else { /* * Sanity typecheck of the target object: * * If 1) This is the last segment (num_segments == 0) * 2) And we are looking for a specific type * (Not checking for TYPE_ANY) * 3) Which is not an alias * 4) Which is not a local type (TYPE_SCOPE) * 5) And the type of target object is known (not TYPE_ANY) * 6) And target object does not match what we are looking for * * Then we have a type mismatch. Just warn and ignore it. */ if ((type_to_check_for != ACPI_TYPE_ANY) && (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && (this_node->type != ACPI_TYPE_ANY) && (this_node->type != type_to_check_for)) { /* Complain about a type mismatch */ ACPI_WARNING((AE_INFO, "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", ACPI_CAST_PTR(char, &simple_name), acpi_ut_get_type_name(this_node-> type), acpi_ut_get_type_name (type_to_check_for))); } /* * If this is the last name segment and we are not looking for a * specific type, but the type of found object is known, use that * type to (later) see if it opens a scope. */ if (type == ACPI_TYPE_ANY) { type = this_node->type; } } /* Point to next name segment and make this node current */ path += ACPI_NAME_SIZE; current_node = this_node; }
void acpi_ut_dump_buffer2(u8 * buffer, u32 count, u32 display) { u32 i = 0; u32 j; u32 temp32; u8 buf_char; if (!buffer) { acpi_os_printf("Null Buffer Pointer in DumpBuffer!\n"); return; } if ((count < 4) || (count & 0x01)) { display = DB_BYTE_DISPLAY; } /* Nasty little dump buffer routine! */ while (i < count) { /* Print current offset */ acpi_os_printf("%6.4X: ", i); /* Print 16 hex chars */ for (j = 0; j < 16;) { if (i + j >= count) { /* Dump fill spaces */ acpi_os_printf("%*s", ((display * 2) + 1), " "); j += display; continue; } switch (display) { case DB_BYTE_DISPLAY: default: /* Default is BYTE display */ acpi_os_printf("%02X ", buffer[(acpi_size) i + j]); break; case DB_WORD_DISPLAY: ACPI_MOVE_16_TO_32(&temp32, &buffer[(acpi_size) i + j]); acpi_os_printf("%04X ", temp32); break; case DB_DWORD_DISPLAY: ACPI_MOVE_32_TO_32(&temp32, &buffer[(acpi_size) i + j]); acpi_os_printf("%08X ", temp32); break; case DB_QWORD_DISPLAY: ACPI_MOVE_32_TO_32(&temp32, &buffer[(acpi_size) i + j]); acpi_os_printf("%08X", temp32); ACPI_MOVE_32_TO_32(&temp32, &buffer[(acpi_size) i + j + 4]); acpi_os_printf("%08X ", temp32); break; } j += display; } /* * Print the ASCII equivalent characters but watch out for the bad * unprintable ones (printable chars are 0x20 through 0x7E) */ acpi_os_printf(" "); for (j = 0; j < 16; j++) { if (i + j >= count) { acpi_os_printf("\n"); return; } buf_char = buffer[(acpi_size) i + j]; if (ACPI_IS_PRINT(buf_char)) { acpi_os_printf("%c", buf_char); } else { acpi_os_printf("."); } } /* Done with that line. */ acpi_os_printf("\n"); i += 16; } return; }
void acpi_ps_get_next_simple_arg ( struct acpi_parse_state *parser_state, u32 arg_type, union acpi_parse_object *arg) { ACPI_FUNCTION_TRACE_U32 ("ps_get_next_simple_arg", arg_type); switch (arg_type) { case ARGP_BYTEDATA: acpi_ps_init_op (arg, AML_BYTE_OP); arg->common.value.integer = (u32) ACPI_GET8 (parser_state->aml); parser_state->aml++; break; case ARGP_WORDDATA: acpi_ps_init_op (arg, AML_WORD_OP); /* Get 2 bytes from the AML stream */ ACPI_MOVE_16_TO_32 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 2; break; case ARGP_DWORDDATA: acpi_ps_init_op (arg, AML_DWORD_OP); /* Get 4 bytes from the AML stream */ ACPI_MOVE_32_TO_32 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 4; break; case ARGP_QWORDDATA: acpi_ps_init_op (arg, AML_QWORD_OP); /* Get 8 bytes from the AML stream */ ACPI_MOVE_64_TO_64 (&arg->common.value.integer, parser_state->aml); parser_state->aml += 8; break; case ARGP_CHARLIST: acpi_ps_init_op (arg, AML_STRING_OP); arg->common.value.string = (char *) parser_state->aml; while (ACPI_GET8 (parser_state->aml) != '\0') { parser_state->aml++; } parser_state->aml++; break; case ARGP_NAME: case ARGP_NAMESTRING: acpi_ps_init_op (arg, AML_INT_NAMEPATH_OP); arg->common.value.name = acpi_ps_get_next_namestring (parser_state); break; default: ACPI_REPORT_ERROR (("Invalid arg_type %X\n", arg_type)); break; } return_VOID; }
ACPI_STATUS AcpiEvMatchGpeMethod ( ACPI_HANDLE ObjHandle, UINT32 Level, void *Context, void **ReturnValue) { ACPI_NAMESPACE_NODE *MethodNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); ACPI_GPE_WALK_INFO *WalkInfo = ACPI_CAST_PTR (ACPI_GPE_WALK_INFO, Context); ACPI_GPE_EVENT_INFO *GpeEventInfo; UINT32 GpeNumber; char Name[ACPI_NAME_SIZE + 1]; UINT8 Type; ACPI_FUNCTION_TRACE (EvMatchGpeMethod); /* Check if requested OwnerId matches this OwnerId */ if ((WalkInfo->ExecuteByOwnerId) && (MethodNode->OwnerId != WalkInfo->OwnerId)) { return_ACPI_STATUS (AE_OK); } /* * Match and decode the _Lxx and _Exx GPE method names * * 1) Extract the method name and null terminate it */ ACPI_MOVE_32_TO_32 (Name, &MethodNode->Name.Integer); Name[ACPI_NAME_SIZE] = 0; /* 2) Name must begin with an underscore */ if (Name[0] != '_') { return_ACPI_STATUS (AE_OK); /* Ignore this method */ } /* * 3) Edge/Level determination is based on the 2nd character * of the method name */ switch (Name[1]) { case 'L': Type = ACPI_GPE_LEVEL_TRIGGERED; break; case 'E': Type = ACPI_GPE_EDGE_TRIGGERED; break; default: /* Unknown method type, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Ignoring unknown GPE method type: %s " "(name not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* 4) The last two characters of the name are the hex GPE Number */ GpeNumber = ACPI_STRTOUL (&Name[2], NULL, 16); if (GpeNumber == ACPI_UINT32_MAX) { /* Conversion failed; invalid method, just ignore it */ ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Could not extract GPE number from name: %s " "(name is not of form _Lxx or _Exx)", Name)); return_ACPI_STATUS (AE_OK); } /* Ensure that we have a valid GPE number for this GPE block */ GpeEventInfo = AcpiEvLowGetGpeInfo (GpeNumber, WalkInfo->GpeBlock); if (!GpeEventInfo) { /* * This GpeNumber is not valid for this GPE block, just ignore it. * However, it may be valid for a different GPE block, since GPE0 * and GPE1 methods both appear under \_GPE. */ return_ACPI_STATUS (AE_OK); } if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_HANDLER) { /* If there is already a handler, ignore this GPE method */ return_ACPI_STATUS (AE_OK); } if ((GpeEventInfo->Flags & ACPI_GPE_DISPATCH_MASK) == ACPI_GPE_DISPATCH_METHOD) { /* * If there is already a method, ignore this method. But check * for a type mismatch (if both the _Lxx AND _Exx exist) */ if (Type != (GpeEventInfo->Flags & ACPI_GPE_XRUPT_TYPE_MASK)) { ACPI_ERROR ((AE_INFO, "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", GpeNumber, GpeNumber, GpeNumber)); } return_ACPI_STATUS (AE_OK); } /* * Add the GPE information from above to the GpeEventInfo block for * use during dispatch of this GPE. */ GpeEventInfo->Flags &= ~(ACPI_GPE_DISPATCH_MASK); GpeEventInfo->Flags |= (UINT8) (Type | ACPI_GPE_DISPATCH_METHOD); GpeEventInfo->Dispatch.MethodNode = MethodNode; ACPI_DEBUG_PRINT ((ACPI_DB_LOAD, "Registered GPE method %s as GPE number 0x%.2X\n", Name, GpeNumber)); return_ACPI_STATUS (AE_OK); }
/******************************************************************************* * * FUNCTION: acpi_decode_pld_buffer * * PARAMETERS: in_buffer - Buffer returned by _PLD method * length - Length of the in_buffer * return_buffer - Where the decode buffer is returned * * RETURN: Status and the decoded _PLD buffer. User must deallocate * the buffer via ACPI_FREE. * * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into * a local struct that is much more useful to an ACPI driver. * ******************************************************************************/ acpi_status acpi_decode_pld_buffer(u8 *in_buffer, acpi_size length, struct acpi_pld_info ** return_buffer) { struct acpi_pld_info *pld_info; u32 *buffer = ACPI_CAST_PTR(u32, in_buffer); u32 dword; /* Parameter validation */ if (!in_buffer || !return_buffer || (length < 16)) { return (AE_BAD_PARAMETER); } pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info)); if (!pld_info) { return (AE_NO_MEMORY); } /* First 32-bit DWord */ ACPI_MOVE_32_TO_32(&dword, &buffer[0]); pld_info->revision = ACPI_PLD_GET_REVISION(&dword); pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword); pld_info->color = ACPI_PLD_GET_COLOR(&dword); /* Second 32-bit DWord */ ACPI_MOVE_32_TO_32(&dword, &buffer[1]); pld_info->width = ACPI_PLD_GET_WIDTH(&dword); pld_info->height = ACPI_PLD_GET_HEIGHT(&dword); /* Third 32-bit DWord */ ACPI_MOVE_32_TO_32(&dword, &buffer[2]); pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword); pld_info->dock = ACPI_PLD_GET_DOCK(&dword); pld_info->lid = ACPI_PLD_GET_LID(&dword); pld_info->panel = ACPI_PLD_GET_PANEL(&dword); pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword); pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword); pld_info->shape = ACPI_PLD_GET_SHAPE(&dword); pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword); pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword); pld_info->group_position = ACPI_PLD_GET_POSITION(&dword); pld_info->bay = ACPI_PLD_GET_BAY(&dword); /* Fourth 32-bit DWord */ ACPI_MOVE_32_TO_32(&dword, &buffer[3]); pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword); pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword); pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword); pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword); pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword); pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword); pld_info->order = ACPI_PLD_GET_ORDER(&dword); if (length >= ACPI_PLD_BUFFER_SIZE) { /* Fifth 32-bit DWord (Revision 2 of _PLD) */ ACPI_MOVE_32_TO_32(&dword, &buffer[4]); pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword); pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword); } *return_buffer = pld_info; return (AE_OK); }