acpi_status acpi_tb_find_table(char *signature, char *oem_id, char *oem_table_id, struct acpi_table_header ** table_ptr) { acpi_status status; struct acpi_table_header *table; ACPI_FUNCTION_TRACE("tb_find_table"); /* Validate string lengths */ if ((ACPI_STRLEN(signature) > ACPI_NAME_SIZE) || (ACPI_STRLEN(oem_id) > sizeof(table->oem_id)) || (ACPI_STRLEN(oem_table_id) > sizeof(table->oem_table_id))) { return_ACPI_STATUS(AE_AML_STRING_LIMIT); } if (!ACPI_STRNCMP(signature, DSDT_SIG, ACPI_NAME_SIZE)) { /* * The DSDT pointer is contained in the FADT, not the RSDT. * This code should suffice, because the only code that would perform * a "find" on the DSDT is the data_table_region() AML opcode -- in * which case, the DSDT is guaranteed to be already loaded. * If this becomes insufficient, the FADT will have to be found first. */ if (!acpi_gbl_DSDT) { return_ACPI_STATUS(AE_NO_ACPI_TABLES); } table = acpi_gbl_DSDT; } else { /* Find the table */ status = acpi_get_firmware_table(signature, 1, ACPI_LOGICAL_ADDRESSING, &table); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Check oem_id and oem_table_id */ if ((oem_id[0] && ACPI_STRNCMP(oem_id, table->oem_id, sizeof(table->oem_id))) || (oem_table_id[0] && ACPI_STRNCMP(oem_table_id, table->oem_table_id, sizeof(table->oem_table_id)))) { return_ACPI_STATUS(AE_AML_NAME_NOT_FOUND); } ACPI_DEBUG_PRINT((ACPI_DB_TABLES, "Found table [%4.4s]\n", table->signature)); *table_ptr = table; return_ACPI_STATUS(AE_OK); }
acpi_status acpi_tb_validate_rsdt ( struct acpi_table_header *table_ptr) { int no_match; ACPI_FUNCTION_NAME ("tb_validate_rsdt"); /* * For RSDP revision 0 or 1, we use the RSDT. * For RSDP revision 2 and above, we use the XSDT */ if (acpi_gbl_RSDP->revision < 2) { no_match = ACPI_STRNCMP ((char *) table_ptr, RSDT_SIG, sizeof (RSDT_SIG) -1); } else { no_match = ACPI_STRNCMP ((char *) table_ptr, XSDT_SIG, sizeof (XSDT_SIG) -1); } if (no_match) { /* Invalid RSDT or XSDT signature */ ACPI_REPORT_ERROR (("Invalid signature where RSDP indicates RSDT/XSDT should be located\n")); ACPI_DUMP_BUFFER (acpi_gbl_RSDP, 20); ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ERROR, "RSDT/XSDT signature at %X (%p) is invalid\n", acpi_gbl_RSDP->rsdt_physical_address, (void *) (acpi_native_uint) acpi_gbl_RSDP->rsdt_physical_address)); if (acpi_gbl_RSDP->revision < 2) { ACPI_REPORT_ERROR (("Looking for RSDT (RSDP->Rev < 2)\n")) } else { ACPI_REPORT_ERROR (("Looking for XSDT (RSDP->Rev >= 2)\n")) } ACPI_DUMP_BUFFER ((char *) table_ptr, 48); return (AE_BAD_SIGNATURE); } return (AE_OK); }
acpi_status acpi_tb_validate_rsdp(struct rsdp_descriptor *rsdp) { ACPI_FUNCTION_ENTRY(); /* * The signature and checksum must both be correct */ if (ACPI_STRNCMP((char *)rsdp, RSDP_SIG, sizeof(RSDP_SIG) - 1) != 0) { /* Nope, BAD Signature */ return (AE_BAD_SIGNATURE); } /* Check the standard checksum */ if (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && (acpi_tb_generate_checksum(rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } return (AE_OK); }
static acpi_status acpi_tb_validate_rsdp(struct acpi_table_rsdp *rsdp) { ACPI_FUNCTION_ENTRY(); /* * The signature and checksum must both be correct * * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ if (ACPI_STRNCMP((char *)rsdp, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1) != 0) { /* Nope, BAD Signature */ return (AE_BAD_SIGNATURE); } /* Check the standard checksum */ if (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((rsdp->revision >= 2) && (acpi_tb_checksum((u8 *) rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } return (AE_OK); }
static u8 acpi_ev_match_pci_root_bridge(char *id) { /* * Check if this is a PCI root. * ACPI 3.0+: check for a PCI Express root also. */ if (!(ACPI_STRNCMP(id, PCI_ROOT_HID_STRING, sizeof(PCI_ROOT_HID_STRING))) || !(ACPI_STRNCMP(id, PCI_EXPRESS_ROOT_HID_STRING, sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { return (TRUE); } return (FALSE); }
ACPI_STATUS AcpiTbGetSecondaryTable ( ACPI_POINTER *Address, ACPI_STRING Signature, ACPI_TABLE_DESC *TableInfo) { ACPI_STATUS Status; ACPI_TABLE_HEADER Header; ACPI_FUNCTION_TRACE_STR ("TbGetSecondaryTable", Signature); /* Get the header in order to match the signature */ Status = AcpiTbGetTableHeader (Address, &Header); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Signature must match request */ if (ACPI_STRNCMP (Header.Signature, Signature, ACPI_NAME_SIZE)) { ACPI_REPORT_ERROR (("Incorrect table signature - wanted [%s] found [%4.4s]\n", Signature, Header.Signature)); return_ACPI_STATUS (AE_BAD_SIGNATURE); } /* * Check the table signature and make sure it is recognized. * Also checks the header checksum */ TableInfo->Pointer = &Header; Status = AcpiTbRecognizeTable (TableInfo, ACPI_TABLE_SECONDARY); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Get the entire table */ Status = AcpiTbGetTableBody (Address, &Header, TableInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } /* Install the table */ Status = AcpiTbInstallTable (TableInfo); return_ACPI_STATUS (Status); }
static BOOLEAN AcpiEvMatchPciRootBridge ( char *Id) { /* * Check if this is a PCI root. * ACPI 3.0+: check for a PCI Express root also. */ if (!(ACPI_STRNCMP (Id, PCI_ROOT_HID_STRING, sizeof (PCI_ROOT_HID_STRING))) || !(ACPI_STRNCMP (Id, PCI_EXPRESS_ROOT_HID_STRING, sizeof (PCI_EXPRESS_ROOT_HID_STRING)))) { return (TRUE); } return (FALSE); }
static acpi_status acpi_tb_get_secondary_table ( struct acpi_pointer *address, acpi_string signature, struct acpi_table_desc *table_info) { acpi_status status; struct acpi_table_header header; ACPI_FUNCTION_TRACE_STR ("tb_get_secondary_table", signature); /* Get the header in order to match the signature */ status = acpi_tb_get_table_header (address, &header); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Signature must match request */ if (ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { ACPI_REPORT_ERROR (( "Incorrect table signature - wanted [%s] found [%4.4s]\n", signature, header.signature)); return_ACPI_STATUS (AE_BAD_SIGNATURE); } /* * Check the table signature and make sure it is recognized. * Also checks the header checksum */ table_info->pointer = &header; status = acpi_tb_recognize_table (table_info, ACPI_TABLE_SECONDARY); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Get the entire table */ status = acpi_tb_get_table_body (address, &header, table_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Install the table */ status = acpi_tb_install_table (table_info); return_ACPI_STATUS (status); }
static ACPI_STATUS AcpiTbMatchSignature ( char *Signature, ACPI_TABLE_DESC *TableInfo, UINT8 SearchType) { ACPI_NATIVE_UINT i; ACPI_FUNCTION_TRACE (TbMatchSignature); /* Search for a signature match among the known table types */ for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++) { if (!(AcpiGbl_TableData[i].Flags & SearchType)) { continue; } if (!ACPI_STRNCMP (Signature, AcpiGbl_TableData[i].Signature, AcpiGbl_TableData[i].SigLength)) { /* Found a signature match, return index if requested */ if (TableInfo) { TableInfo->Type = (UINT8) i; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", (char *) AcpiGbl_TableData[i].Signature)); return_ACPI_STATUS (AE_OK); } } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", (char *) Signature)); return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED); }
acpi_status acpi_tb_match_signature ( char *signature, struct acpi_table_desc *table_info, u8 search_type) { acpi_native_uint i; ACPI_FUNCTION_TRACE ("tb_match_signature"); /* * Search for a signature match among the known table types */ for (i = 0; i < NUM_ACPI_TABLE_TYPES; i++) { if (!(acpi_gbl_table_data[i].flags & search_type)) { continue; } if (!ACPI_STRNCMP (signature, acpi_gbl_table_data[i].signature, acpi_gbl_table_data[i].sig_length)) { /* Found a signature match, return index if requested */ if (table_info) { table_info->type = (u8) i; } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is an ACPI table consumed by the core subsystem\n", (char *) acpi_gbl_table_data[i].signature)); return_ACPI_STATUS (AE_OK); } } ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "Table [%4.4s] is not an ACPI table consumed by the core subsystem - ignored\n", (char *) signature)); return_ACPI_STATUS (AE_TABLE_NOT_SUPPORTED); }
void AcpiDbUnloadAcpiTable ( char *TableArg, char *InstanceArg) { /* TBD: Need to reimplement for new data structures */ #if 0 UINT32 i; ACPI_STATUS Status; /* Search all tables for the target type */ for (i = 0; i < (ACPI_TABLE_ID_MAX+1); i++) { if (!ACPI_STRNCMP (TableArg, AcpiGbl_TableData[i].Signature, AcpiGbl_TableData[i].SigLength)) { /* Found the table, unload it */ Status = AcpiUnloadTable (i); if (ACPI_SUCCESS (Status)) { AcpiOsPrintf ("[%s] unloaded and uninstalled\n", TableArg); } else { AcpiOsPrintf ("%s, while unloading [%s]\n", AcpiFormatException (Status), TableArg); } return; } } AcpiOsPrintf ("Unknown table type [%s]\n", TableArg); #endif }
static ACPI_STATUS AcpiTbValidateRsdp ( ACPI_TABLE_RSDP *Rsdp) { ACPI_FUNCTION_ENTRY (); /* * The signature and checksum must both be correct * * Note: Sometimes there exists more than one RSDP in memory; the valid * RSDP has a valid checksum, all others have an invalid checksum. */ if (ACPI_STRNCMP ((char *) Rsdp, ACPI_SIG_RSDP, sizeof (ACPI_SIG_RSDP)-1) != 0) { /* Nope, BAD Signature */ return (AE_BAD_SIGNATURE); } /* Check the standard checksum */ if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { return (AE_BAD_CHECKSUM); } /* Check extended checksum if table version >= 2 */ if ((Rsdp->Revision >= 2) && (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) { return (AE_BAD_CHECKSUM); } return (AE_OK); }
UINT8 * AcpiTbScanMemoryForRsdp ( UINT8 *StartAddress, UINT32 Length) { UINT32 Offset; UINT8 *MemRover; ACPI_FUNCTION_TRACE ("TbScanMemoryForRsdp"); /* Search from given start addr for the requested length */ for (Offset = 0, MemRover = StartAddress; Offset < Length; Offset += ACPI_RSDP_SCAN_STEP, MemRover += ACPI_RSDP_SCAN_STEP) { /* The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) MemRover, RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 && AcpiTbChecksum (MemRover, ACPI_RSDP_CHECKSUM_LENGTH) == 0) { /* If so, we have found the RSDP */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at physical address %p\n",MemRover)); return_PTR (MemRover); } } /* Searched entire block, no RSDP was found */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.\n")); return_PTR (NULL); }
static BOOLEAN OpcFindName ( char **List, char *Name, UINT64 *Index) { char *Str; UINT32 i; OpcStrupr (Name); for (i = 0, Str = List[0]; Str; i++, Str = List[i]) { if (!(ACPI_STRNCMP (Str, Name, ACPI_STRLEN (Name)))) { *Index = i; return (TRUE); } } return (FALSE); }
u8 * acpi_tb_scan_memory_for_rsdp ( u8 *start_address, u32 length) { u32 offset; u8 *mem_rover; ACPI_FUNCTION_TRACE ("tb_scan_memory_for_rsdp"); /* Search from given start addr for the requested length */ for (offset = 0, mem_rover = start_address; offset < length; offset += ACPI_RSDP_SCAN_STEP, mem_rover += ACPI_RSDP_SCAN_STEP) { /* The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) mem_rover, RSDP_SIG, sizeof (RSDP_SIG)-1) == 0 && acpi_tb_checksum (mem_rover, ACPI_RSDP_CHECKSUM_LENGTH) == 0) { /* If so, we have found the RSDP */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at physical address %p\n",mem_rover)); return_PTR (mem_rover); } } /* Searched entire block, no RSDP was found */ ACPI_DEBUG_PRINT ((ACPI_DB_INFO,"Searched entire block, no RSDP was found.\n")); return_PTR (NULL); }
acpi_status acpi_walk_resources ( acpi_handle device_handle, char *path, ACPI_WALK_RESOURCE_CALLBACK user_function, void *context) { acpi_status status; struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; struct acpi_resource *resource; struct acpi_resource *buffer_end; ACPI_FUNCTION_TRACE ("acpi_walk_resources"); if (!device_handle || (ACPI_STRNCMP (path, METHOD_NAME__CRS, sizeof (METHOD_NAME__CRS)) && ACPI_STRNCMP (path, METHOD_NAME__PRS, sizeof (METHOD_NAME__PRS)))) { return_ACPI_STATUS (AE_BAD_PARAMETER); } status = acpi_rs_get_method_data (device_handle, path, &buffer); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } /* Setup pointers */ resource = (struct acpi_resource *) buffer.pointer; buffer_end = ACPI_CAST_PTR (struct acpi_resource, ((u8 *) buffer.pointer + buffer.length)); /* Walk the resource list */ for (;;) { if (!resource || resource->id == ACPI_RSTYPE_END_TAG) { break; } status = user_function (resource, context); switch (status) { case AE_OK: case AE_CTRL_DEPTH: /* Just keep going */ status = AE_OK; break; case AE_CTRL_TERMINATE: /* Exit now, with OK stats */ status = AE_OK; goto cleanup; default: /* All others are valid exceptions */ goto cleanup; } /* Get the next resource descriptor */ resource = ACPI_NEXT_RESOURCE (resource); /* Check for end-of-buffer */ if (resource >= buffer_end) { goto cleanup; } } cleanup: acpi_os_free (buffer.pointer); return_ACPI_STATUS (status); }
acpi_status acpi_ex_load_op(union acpi_operand_object *obj_desc, union acpi_operand_object *target, struct acpi_walk_state *walk_state) { acpi_status status; union acpi_operand_object *ddb_handle; union acpi_operand_object *buffer_desc = NULL; struct acpi_table_header *table_ptr = NULL; acpi_physical_address address; struct acpi_table_header table_header; u32 i; ACPI_FUNCTION_TRACE("ex_load_op"); /* Object can be either an op_region or a Field */ switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { case ACPI_TYPE_REGION: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Region %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); /* * If the Region Address and Length have not been previously evaluated, * evaluate them now and save the results. */ if (!(obj_desc->common.flags & AOPOBJ_DATA_VALID)) { status = acpi_ds_get_region_arguments(obj_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Get the base physical address of the region */ address = obj_desc->region.address; /* Get the table length from the table header */ table_header.length = 0; for (i = 0; i < 8; i++) { status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, ((u8 *) & table_header) + i); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Sanity check the table length */ if (table_header.length < sizeof(struct acpi_table_header)) { return_ACPI_STATUS(AE_BAD_HEADER); } /* Allocate a buffer for the entire table */ table_ptr = ACPI_MEM_ALLOCATE(table_header.length); if (!table_ptr) { return_ACPI_STATUS(AE_NO_MEMORY); } /* Get the entire table from the op region */ for (i = 0; i < table_header.length; i++) { status = acpi_ev_address_space_dispatch(obj_desc, ACPI_READ, (acpi_physical_address) (i + address), 8, ((u8 *) table_ptr + i)); if (ACPI_FAILURE(status)) { goto cleanup; } } break; case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Load from Field %p %s\n", obj_desc, acpi_ut_get_object_type_name(obj_desc))); /* * The length of the field must be at least as large as the table. * Read the entire field and thus the entire table. Buffer is * allocated during the read. */ status = acpi_ex_read_data_from_field(walk_state, obj_desc, &buffer_desc); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } table_ptr = ACPI_CAST_PTR(struct acpi_table_header, buffer_desc->buffer.pointer); /* All done with the buffer_desc, delete it */ buffer_desc->buffer.pointer = NULL; acpi_ut_remove_reference(buffer_desc); /* Sanity check the table length */ if (table_ptr->length < sizeof(struct acpi_table_header)) { status = AE_BAD_HEADER; goto cleanup; } break; default: return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } /* The table must be either an SSDT or a PSDT */ if ((!ACPI_STRNCMP(table_ptr->signature, acpi_gbl_table_data[ACPI_TABLE_PSDT].signature, acpi_gbl_table_data[ACPI_TABLE_PSDT].sig_length)) && (!ACPI_STRNCMP(table_ptr->signature, acpi_gbl_table_data[ACPI_TABLE_SSDT].signature, acpi_gbl_table_data[ACPI_TABLE_SSDT].sig_length))) { ACPI_ERROR((AE_INFO, "Table has invalid signature [%4.4s], must be SSDT or PSDT", table_ptr->signature)); status = AE_BAD_SIGNATURE; goto cleanup; } /* Install the new table into the local data structures */ status = acpi_ex_add_table(table_ptr, acpi_gbl_root_node, &ddb_handle); if (ACPI_FAILURE(status)) { /* On error, table_ptr was deallocated above */ return_ACPI_STATUS(status); } /* Store the ddb_handle into the Target operand */ status = acpi_ex_store(ddb_handle, target, walk_state); if (ACPI_FAILURE(status)) { (void)acpi_ex_unload_table(ddb_handle); /* table_ptr was deallocated above */ return_ACPI_STATUS(status); } cleanup: if (ACPI_FAILURE(status)) { ACPI_MEM_FREE(table_ptr); } return_ACPI_STATUS(status); }
/******************************************************************************* * * FUNCTION: acpi_ns_get_device_callback * * PARAMETERS: Callback from acpi_get_device * * RETURN: Status * * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non- * present devices, or if they specified a HID, it filters based * on that. * ******************************************************************************/ static acpi_status acpi_ns_get_device_callback(acpi_handle obj_handle, u32 nesting_level, void *context, void **return_value) { struct acpi_get_devices_info *info = context; acpi_status status; struct acpi_namespace_node *node; u32 flags; struct acpica_device_id hid; struct acpi_compatible_id_list *cid; acpi_native_uint i; status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } node = acpi_ns_map_handle_to_node(obj_handle); status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { return (status); } if (!node) { return (AE_BAD_PARAMETER); } /* Run _STA to determine if device is present */ status = acpi_ut_execute_STA(node, &flags); if (ACPI_FAILURE(status)) { return (AE_CTRL_DEPTH); } if (!(flags & ACPI_STA_DEVICE_PRESENT)) { /* Don't examine children of the device if not present */ return (AE_CTRL_DEPTH); } /* Filter based on device HID & CID */ if (info->hid != NULL) { status = acpi_ut_execute_HID(node, &hid); if (status == AE_NOT_FOUND) { return (AE_OK); } else if (ACPI_FAILURE(status)) { return (AE_CTRL_DEPTH); } if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { /* Get the list of Compatible IDs */ status = acpi_ut_execute_CID(node, &cid); if (status == AE_NOT_FOUND) { return (AE_OK); } else if (ACPI_FAILURE(status)) { return (AE_CTRL_DEPTH); } /* Walk the CID list */ for (i = 0; i < cid->count; i++) { if (ACPI_STRNCMP(cid->id[i].value, info->hid, sizeof(struct acpi_compatible_id)) != 0) { ACPI_FREE(cid); return (AE_OK); } } ACPI_FREE(cid); } } status = info->user_function(obj_handle, nesting_level, info->context, return_value); return (status); }
static ACPI_STATUS AcpiDmLoadDescendingOp ( ACPI_PARSE_OBJECT *Op, UINT32 Level, void *Context) { ACPI_OP_WALK_INFO *Info = Context; const ACPI_OPCODE_INFO *OpInfo; ACPI_WALK_STATE *WalkState; ACPI_OBJECT_TYPE ObjectType; ACPI_STATUS Status; char *Path = NULL; ACPI_PARSE_OBJECT *NextOp; ACPI_NAMESPACE_NODE *Node; char FieldPath[5]; BOOLEAN PreDefined = FALSE; UINT8 PreDefineIndex = 0; WalkState = Info->WalkState; OpInfo = AcpiPsGetOpcodeInfo (Op->Common.AmlOpcode); ObjectType = OpInfo->ObjectType; ObjectType = AslMapNamedOpcodeToDataType (Op->Asl.AmlOpcode); /* Only interested in operators that create new names */ if (!(OpInfo->Flags & AML_NAMED) && !(OpInfo->Flags & AML_CREATE)) { goto Exit; } /* Get the NamePath from the appropriate place */ if (OpInfo->Flags & AML_NAMED) { /* For all named operators, get the new name */ Path = (char *) Op->Named.Path; if (!Path && Op->Common.AmlOpcode == AML_INT_NAMEDFIELD_OP) { *ACPI_CAST_PTR (UINT32, &FieldPath[0]) = Op->Named.Name; FieldPath[4] = 0; Path = FieldPath; } } else if (OpInfo->Flags & AML_CREATE) { /* New name is the last child */ NextOp = Op->Common.Value.Arg; while (NextOp->Common.Next) { NextOp = NextOp->Common.Next; } Path = NextOp->Common.Value.String; } if (!Path) { goto Exit; } /* Insert the name into the namespace */ Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ObjectType, ACPI_IMODE_LOAD_PASS2, ACPI_NS_DONT_OPEN_SCOPE, WalkState, &Node); Op->Common.Node = Node; if (ACPI_SUCCESS (Status)) { /* Check if it's a predefined node */ while (AcpiGbl_PreDefinedNames[PreDefineIndex].Name) { if (!ACPI_STRNCMP (Node->Name.Ascii, AcpiGbl_PreDefinedNames[PreDefineIndex].Name, 4)) { PreDefined = TRUE; break; } PreDefineIndex++; } /* * Set node owner id if it satisfies all the following conditions: * 1) Not a predefined node, _SB_ etc * 2) Not the root node * 3) Not a node created by Scope */ if (!PreDefined && Node != AcpiGbl_RootNode && Op->Common.AmlOpcode != AML_SCOPE_OP) { Node->OwnerId = WalkState->OwnerId; } } Exit: if (AcpiNsOpensScope (ObjectType)) { if (Op->Common.Node) { Status = AcpiDsScopeStackPush (Op->Common.Node, ObjectType, WalkState); if (ACPI_FAILURE (Status)) { return (Status); } } } return (AE_OK); }
static ACPI_STATUS AcpiNsGetDeviceCallback ( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue) { ACPI_GET_DEVICES_INFO *Info = Context; ACPI_STATUS Status; ACPI_NAMESPACE_NODE *Node; UINT32 Flags; ACPI_DEVICE_ID Hid; ACPI_COMPATIBLE_ID_LIST *Cid; UINT32 i; BOOLEAN Found; Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } Node = AcpiNsMapHandleToNode (ObjHandle); Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); if (ACPI_FAILURE (Status)) { return (Status); } if (!Node) { return (AE_BAD_PARAMETER); } /* Run _STA to determine if device is present */ Status = AcpiUtExecute_STA (Node, &Flags); if (ACPI_FAILURE (Status)) { return (AE_CTRL_DEPTH); } if (!(Flags & ACPI_STA_DEVICE_PRESENT) && !(Flags & ACPI_STA_DEVICE_FUNCTIONING)) { /* * Don't examine the children of the device only when the * device is neither present nor functional. See ACPI spec, * description of _STA for more information. */ return (AE_CTRL_DEPTH); } /* Filter based on device HID & CID */ if (Info->Hid != NULL) { Status = AcpiUtExecute_HID (Node, &Hid); if (Status == AE_NOT_FOUND) { return (AE_OK); } else if (ACPI_FAILURE (Status)) { return (AE_CTRL_DEPTH); } if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0) { /* * HID does not match, attempt match within the * list of Compatible IDs (CIDs) */ Status = AcpiUtExecute_CID (Node, &Cid); if (Status == AE_NOT_FOUND) { return (AE_OK); } else if (ACPI_FAILURE (Status)) { return (AE_CTRL_DEPTH); } /* Walk the CID list */ Found = FALSE; for (i = 0; i < Cid->Count; i++) { if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid, sizeof (ACPI_COMPATIBLE_ID)) == 0) { /* Found a matching CID */ Found = TRUE; break; } } ACPI_FREE (Cid); if (!Found) { return (AE_OK); } } } /* We have a valid device, invoke the user function */ Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context, ReturnValue); return (Status); }
acpi_status acpi_ev_pci_config_region_setup(acpi_handle handle, u32 function, void *handler_context, void **region_context) { acpi_status status = AE_OK; acpi_integer pci_value; struct acpi_pci_id *pci_id = *region_context; union acpi_operand_object *handler_obj; struct acpi_namespace_node *parent_node; struct acpi_namespace_node *pci_root_node; union acpi_operand_object *region_obj = (union acpi_operand_object *)handle; struct acpi_device_id object_hID; ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); handler_obj = region_obj->region.handler; if (!handler_obj) { /* * No installed handler. This shouldn't happen because the dispatch * routine checks before we get here, but we check again just in case. */ ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, "Attempting to init a region %p, with no handler\n", region_obj)); return_ACPI_STATUS(AE_NOT_EXIST); } *region_context = NULL; if (function == ACPI_REGION_DEACTIVATE) { if (pci_id) { ACPI_FREE(pci_id); } return_ACPI_STATUS(status); } parent_node = acpi_ns_get_parent_node(region_obj->region.node); /* * Get the _SEG and _BBN values from the device upon which the handler * is installed. * * We need to get the _SEG and _BBN objects relative to the PCI BUS device. * This is the device the handler has been registered to handle. */ /* * If the address_space.Node is still pointing to the root, we need * to scan upward for a PCI Root bridge and re-associate the op_region * handlers with that device. */ if (handler_obj->address_space.node == acpi_gbl_root_node) { /* Start search from the parent object */ pci_root_node = parent_node; while (pci_root_node != acpi_gbl_root_node) { status = acpi_ut_execute_HID(pci_root_node, &object_hID); if (ACPI_SUCCESS(status)) { /* * Got a valid _HID string, check if this is a PCI root. * New for ACPI 3.0: check for a PCI Express root also. */ if (! (ACPI_STRNCMP (object_hID.value, PCI_ROOT_HID_STRING, sizeof(PCI_ROOT_HID_STRING)) || !(ACPI_STRNCMP (object_hID.value, PCI_EXPRESS_ROOT_HID_STRING, sizeof(PCI_EXPRESS_ROOT_HID_STRING))))) { /* Install a handler for this PCI root bridge */ status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); if (ACPI_FAILURE(status)) { if (status == AE_SAME_HANDLER) { /* * It is OK if the handler is already installed on the root * bridge. Still need to return a context object for the * new PCI_Config operation region, however. */ status = AE_OK; } else { ACPI_EXCEPTION((AE_INFO, status, "Could not install PciConfig handler for Root Bridge %4.4s", acpi_ut_get_node_name (pci_root_node))); } } break; } } pci_root_node = acpi_ns_get_parent_node(pci_root_node); } /* PCI root bridge not found, use namespace root node */ } else { pci_root_node = handler_obj->address_space.node; } /* * If this region is now initialized, we are done. * (install_address_space_handler could have initialized it) */ if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { return_ACPI_STATUS(AE_OK); } /* Region is still not initialized. Create a new context */ pci_id = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pci_id)); if (!pci_id) { return_ACPI_STATUS(AE_NO_MEMORY); } /* * For PCI_Config space access, we need the segment, bus, * device and function numbers. Acquire them here. */ /* * Get the PCI device and function numbers from the _ADR object * contained in the parent's scope. */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node, &pci_value); /* * The default is zero, and since the allocation above zeroed * the data, just do nothing on failure. */ if (ACPI_SUCCESS(status)) { pci_id->device = ACPI_HIWORD(ACPI_LODWORD(pci_value)); pci_id->function = ACPI_LOWORD(ACPI_LODWORD(pci_value)); } /* The PCI segment number comes from the _SEG method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__SEG, pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->segment = ACPI_LOWORD(pci_value); } /* The PCI bus number comes from the _BBN method */ status = acpi_ut_evaluate_numeric_object(METHOD_NAME__BBN, pci_root_node, &pci_value); if (ACPI_SUCCESS(status)) { pci_id->bus = ACPI_LOWORD(pci_value); } /* Complete this device's pci_id */ acpi_os_derive_pci_id(pci_root_node, region_obj->region.node, &pci_id); *region_context = pci_id; return_ACPI_STATUS(AE_OK); }
ACPI_STATUS AcpiGetFirmwareTable ( ACPI_STRING Signature, UINT32 Instance, UINT32 Flags, ACPI_TABLE_HEADER **TablePointer) { ACPI_POINTER RsdpAddress; ACPI_POINTER Address; ACPI_STATUS Status; ACPI_TABLE_HEADER Header; ACPI_TABLE_DESC TableInfo; ACPI_TABLE_DESC RsdtInfo; UINT32 TableCount; UINT32 i; UINT32 j; ACPI_FUNCTION_TRACE ("AcpiGetFirmwareTable"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface */ /* * If we have a buffer, we must have a length too */ if ((Instance == 0) || (!Signature) || (!TablePointer)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } RsdtInfo.Pointer = NULL; if (!AcpiGbl_RSDP) { /* Get the RSDP */ Status = AcpiOsGetRootPointer (Flags, &RsdpAddress); if (ACPI_FAILURE (Status)) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((Flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { Status = AcpiOsMapMemory (RsdpAddress.Pointer.Physical, sizeof (RSDP_DESCRIPTOR), (void **) &AcpiGbl_RSDP); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } } else { AcpiGbl_RSDP = RsdpAddress.Pointer.Logical; } /* * The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) AcpiGbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { /* Nope, BAD Signature */ return_ACPI_STATUS (AE_BAD_SIGNATURE); } if (AcpiTbChecksum (AcpiGbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { /* Nope, BAD Checksum */ return_ACPI_STATUS (AE_BAD_CHECKSUM); } } /* Get the RSDT and validate it */ AcpiTbGetRsdtAddress (&Address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", AcpiGbl_RSDP, ACPI_HIDWORD (Address.Pointer.Value), ACPI_LODWORD (Address.Pointer.Value))); /* Insert ProcessorMode flags */ Address.PointerType |= Flags; Status = AcpiTbGetTable (&Address, &RsdtInfo); if (ACPI_FAILURE (Status)) { return_ACPI_STATUS (Status); } Status = AcpiTbValidateRsdt (RsdtInfo.Pointer); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Get the number of table pointers within the RSDT */ TableCount = AcpiTbGetTableCount (AcpiGbl_RSDP, RsdtInfo.Pointer); Address.PointerType = AcpiGbl_TableFlags | Flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < TableCount; i++) { /* Get the next table pointer, handle RSDT vs. XSDT */ if (AcpiGbl_RSDP->Revision < 2) { Address.Pointer.Value = ((RSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i]; } else { Address.Pointer.Value = ACPI_GET_ADDRESS ( ((XSDT_DESCRIPTOR *) RsdtInfo.Pointer)->TableOffsetEntry[i]); } /* Get the table header */ Status = AcpiTbGetTableHeader (&Address, &Header); if (ACPI_FAILURE (Status)) { goto Cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP (Header.Signature, Signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= Instance) { /* Found the correct instance, get the entire table */ Status = AcpiTbGetTableBody (&Address, &Header, &TableInfo); if (ACPI_FAILURE (Status)) { goto Cleanup; } *TablePointer = TableInfo.Pointer; goto Cleanup; } } } /* Did not find the table */ Status = AE_NOT_EXIST; Cleanup: AcpiOsUnmapMemory (RsdtInfo.Pointer, (ACPI_SIZE) RsdtInfo.Pointer->Length); return_ACPI_STATUS (Status); }
static ACPI_STATUS AcpiDbReadTable ( FILE *fp, ACPI_TABLE_HEADER **Table, UINT32 *TableLength) { ACPI_TABLE_HEADER TableHeader; UINT32 Actual; ACPI_STATUS Status; UINT32 FileSize; BOOLEAN StandardHeader = TRUE; /* Get the file size */ fseek (fp, 0, SEEK_END); FileSize = (UINT32) ftell (fp); fseek (fp, 0, SEEK_SET); if (FileSize < 4) { return (AE_BAD_HEADER); } /* Read the signature */ if (fread (&TableHeader, 1, 4, fp) != 4) { AcpiOsPrintf ("Could not read the table signature\n"); return (AE_BAD_HEADER); } fseek (fp, 0, SEEK_SET); /* The RSDT, FACS and S3PT tables do not have standard ACPI headers */ if (ACPI_COMPARE_NAME (TableHeader.Signature, "RSD ") || ACPI_COMPARE_NAME (TableHeader.Signature, "FACS") || ACPI_COMPARE_NAME (TableHeader.Signature, "S3PT")) { *TableLength = FileSize; StandardHeader = FALSE; } else { /* Read the table header */ if (fread (&TableHeader, 1, sizeof (TableHeader), fp) != sizeof (ACPI_TABLE_HEADER)) { AcpiOsPrintf ("Could not read the table header\n"); return (AE_BAD_HEADER); } #if 0 /* Validate the table header/length */ Status = AcpiTbValidateTableHeader (&TableHeader); if (ACPI_FAILURE (Status)) { AcpiOsPrintf ("Table header is invalid!\n"); return (Status); } #endif /* File size must be at least as long as the Header-specified length */ if (TableHeader.Length > FileSize) { AcpiOsPrintf ( "TableHeader length [0x%X] greater than the input file size [0x%X]\n", TableHeader.Length, FileSize); return (AE_BAD_HEADER); } #ifdef ACPI_OBSOLETE_CODE /* We only support a limited number of table types */ if (ACPI_STRNCMP ((char *) TableHeader.Signature, DSDT_SIG, 4) && ACPI_STRNCMP ((char *) TableHeader.Signature, PSDT_SIG, 4) && ACPI_STRNCMP ((char *) TableHeader.Signature, SSDT_SIG, 4)) { AcpiOsPrintf ("Table signature [%4.4s] is invalid or not supported\n", (char *) TableHeader.Signature); ACPI_DUMP_BUFFER (&TableHeader, sizeof (ACPI_TABLE_HEADER)); return (AE_ERROR); } #endif *TableLength = TableHeader.Length; } /* Allocate a buffer for the table */ *Table = AcpiOsAllocate ((size_t) FileSize); if (!*Table) { AcpiOsPrintf ( "Could not allocate memory for ACPI table %4.4s (size=0x%X)\n", TableHeader.Signature, *TableLength); return (AE_NO_MEMORY); } /* Get the rest of the table */ fseek (fp, 0, SEEK_SET); Actual = fread (*Table, 1, (size_t) FileSize, fp); if (Actual == FileSize) { if (StandardHeader) { /* Now validate the checksum */ Status = AcpiTbVerifyChecksum ((void *) *Table, ACPI_CAST_PTR (ACPI_TABLE_HEADER, *Table)->Length); if (Status == AE_BAD_CHECKSUM) { Status = AcpiDbCheckTextModeCorruption ((UINT8 *) *Table, FileSize, (*Table)->Length); return (Status); } } return (AE_OK); } if (Actual > 0) { AcpiOsPrintf ("Warning - reading table, asked for %X got %X\n", FileSize, Actual); return (AE_OK); } AcpiOsPrintf ("Error - could not read the table file\n"); AcpiOsFree (*Table); *Table = NULL; *TableLength = 0; return (AE_ERROR); }
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; ACPI_NATIVE_UINT Index; UINT32 NumCarats; ACPI_NATIVE_UINT 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_STRNCMP ( &((char *) TargetPath->Pointer)[(NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1], &((char *) CurrentPath->Pointer)[(NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1], ACPI_NAME_SIZE)) { /* Mismatch */ break; } } ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %d", 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] = '^'; } /* * 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] = '^'; 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)", ACPI_STRLEN (NewPath), 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); }
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 = UtStringCacheCalloc (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); }
ACPI_STATUS DtCreateTemplates ( char *Signature) { ACPI_DMTABLE_DATA *TableData; ACPI_STATUS Status; AslInitializeGlobals (); AcpiUtStrupr (Signature); /* Create all known templates if requested */ if (!ACPI_STRNCMP (Signature, "ALL", 3) || !ACPI_STRCMP (Signature, "*")) { Status = DtCreateAllTemplates (); return (Status); } /* * Validate signature and get the template data: * 1) Signature must be 4 characters * 2) Signature must be a recognized ACPI table * 3) There must be a template associated with the signature */ if (strlen (Signature) != ACPI_NAME_SIZE) { fprintf (stderr, "%s, Invalid ACPI table signature\n", Signature); return (AE_ERROR); } /* * Some slack for the two strange tables whose name is different than * their signatures: MADT->APIC and FADT->FACP. */ if (!strcmp (Signature, "MADT")) { Signature = "APIC"; } else if (!strcmp (Signature, "FADT")) { Signature = "FACP"; } TableData = AcpiDmGetTableData (Signature); if (TableData) { if (!TableData->Template) { fprintf (stderr, "%4.4s, No template available\n", Signature); return (AE_ERROR); } } else if (!AcpiUtIsSpecialTable (Signature)) { fprintf (stderr, "%4.4s, Unrecognized ACPI table signature\n", Signature); return (AE_ERROR); } Status = AdInitialize (); if (ACPI_FAILURE (Status)) { return (Status); } Status = DtCreateOneTemplate (Signature, TableData); return (Status); }
acpi_status acpi_get_firmware_table ( acpi_string signature, u32 instance, u32 flags, struct acpi_table_header **table_pointer) { struct acpi_pointer rsdp_address; struct acpi_pointer address; acpi_status status; struct acpi_table_header header; struct acpi_table_desc table_info; struct acpi_table_desc rsdt_info; u32 table_count; u32 i; u32 j; ACPI_FUNCTION_TRACE ("acpi_get_firmware_table"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface */ /* * If we have a buffer, we must have a length too */ if ((instance == 0) || (!signature) || (!table_pointer)) { return_ACPI_STATUS (AE_BAD_PARAMETER); } rsdt_info.pointer = NULL; if (!acpi_gbl_RSDP) { /* Get the RSDP */ status = acpi_os_get_root_pointer (flags, &rsdp_address); if (ACPI_FAILURE (status)) { ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS (AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory (rsdp_address.pointer.physical, sizeof (struct rsdp_descriptor), (void *) &acpi_gbl_RSDP); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } } else { acpi_gbl_RSDP = rsdp_address.pointer.logical; } /* * The signature and checksum must both be correct */ if (ACPI_STRNCMP ((char *) acpi_gbl_RSDP, RSDP_SIG, sizeof (RSDP_SIG)-1) != 0) { /* Nope, BAD Signature */ return_ACPI_STATUS (AE_BAD_SIGNATURE); } if (acpi_tb_checksum (acpi_gbl_RSDP, ACPI_RSDP_CHECKSUM_LENGTH) != 0) { /* Nope, BAD Checksum */ return_ACPI_STATUS (AE_BAD_CHECKSUM); } } /* Get the RSDT and validate it */ acpi_tb_get_rsdt_address (&address); ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, ACPI_HIDWORD (address.pointer.value), ACPI_LODWORD (address.pointer.value))); /* Insert processor_mode flags */ address.pointer_type |= flags; status = acpi_tb_get_table (&address, &rsdt_info); if (ACPI_FAILURE (status)) { return_ACPI_STATUS (status); } status = acpi_tb_validate_rsdt (rsdt_info.pointer); if (ACPI_FAILURE (status)) { goto cleanup; } /* Get the number of table pointers within the RSDT */ table_count = acpi_tb_get_table_count (acpi_gbl_RSDP, rsdt_info.pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < table_count; i++) { /* Get the next table pointer, handle RSDT vs. XSDT */ if (acpi_gbl_RSDP->revision < 2) { address.pointer.value = ((RSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; } else { address.pointer.value = ((XSDT_DESCRIPTOR *) rsdt_info.pointer)->table_offset_entry[i]; } /* Get the table header */ status = acpi_tb_get_table_header (&address, &header); if (ACPI_FAILURE (status)) { goto cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP (header.signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ status = acpi_tb_get_table_body (&address, &header, &table_info); if (ACPI_FAILURE (status)) { goto cleanup; } *table_pointer = table_info.pointer; goto cleanup; } } } /* Did not find the table */ status = AE_NOT_EXIST; cleanup: acpi_os_unmap_memory (rsdt_info.pointer, (acpi_size) rsdt_info.pointer->length); return_ACPI_STATUS (status); }
acpi_status acpi_get_firmware_table(acpi_string signature, u32 instance, u32 flags, struct acpi_table_header **table_pointer) { acpi_status status; struct acpi_pointer address; struct acpi_table_header *header = NULL; struct acpi_table_desc *table_info = NULL; struct acpi_table_desc *rsdt_info; u32 table_count; u32 i; u32 j; ACPI_FUNCTION_TRACE("acpi_get_firmware_table"); /* * Ensure that at least the table manager is initialized. We don't * require that the entire ACPI subsystem is up for this interface. * If we have a buffer, we must have a length too */ if ((instance == 0) || (!signature) || (!table_pointer)) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* Ensure that we have a RSDP */ if (!acpi_gbl_RSDP) { /* Get the RSDP */ status = acpi_os_get_root_pointer(flags, &address); if (ACPI_FAILURE(status)) { ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP not found\n")); return_ACPI_STATUS(AE_NO_ACPI_TABLES); } /* Map and validate the RSDP */ if ((flags & ACPI_MEMORY_MODE) == ACPI_LOGICAL_ADDRESSING) { status = acpi_os_map_memory(address.pointer.physical, sizeof(struct rsdp_descriptor), (void *)&acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else { acpi_gbl_RSDP = address.pointer.logical; } /* The RDSP signature and checksum must both be correct */ status = acpi_tb_validate_rsdp(acpi_gbl_RSDP); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } /* Get the RSDT address via the RSDP */ acpi_tb_get_rsdt_address(&address); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "RSDP located at %p, RSDT physical=%8.8X%8.8X \n", acpi_gbl_RSDP, ACPI_FORMAT_UINT64(address.pointer.value))); /* Insert processor_mode flags */ address.pointer_type |= flags; /* Get and validate the RSDT */ rsdt_info = ACPI_MEM_CALLOCATE(sizeof(struct acpi_table_desc)); if (!rsdt_info) { return_ACPI_STATUS(AE_NO_MEMORY); } status = acpi_tb_get_table(&address, rsdt_info); if (ACPI_FAILURE(status)) { goto cleanup; } status = acpi_tb_validate_rsdt(rsdt_info->pointer); if (ACPI_FAILURE(status)) { goto cleanup; } /* Allocate a scratch table header and table descriptor */ header = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_header)); if (!header) { status = AE_NO_MEMORY; goto cleanup; } table_info = ACPI_MEM_ALLOCATE(sizeof(struct acpi_table_desc)); if (!table_info) { status = AE_NO_MEMORY; goto cleanup; } /* Get the number of table pointers within the RSDT */ table_count = acpi_tb_get_table_count(acpi_gbl_RSDP, rsdt_info->pointer); address.pointer_type = acpi_gbl_table_flags | flags; /* * Search the RSDT/XSDT for the correct instance of the * requested table */ for (i = 0, j = 0; i < table_count; i++) { /* * Get the next table pointer, handle RSDT vs. XSDT * RSDT pointers are 32 bits, XSDT pointers are 64 bits */ if (acpi_gbl_root_table_type == ACPI_TABLE_TYPE_RSDT) { address.pointer.value = (ACPI_CAST_PTR (RSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } else { address.pointer.value = (ACPI_CAST_PTR (XSDT_DESCRIPTOR, rsdt_info->pointer))->table_offset_entry[i]; } /* Get the table header */ status = acpi_tb_get_table_header(&address, header); if (ACPI_FAILURE(status)) { goto cleanup; } /* Compare table signatures and table instance */ if (!ACPI_STRNCMP(header->signature, signature, ACPI_NAME_SIZE)) { /* An instance of the table was found */ j++; if (j >= instance) { /* Found the correct instance, get the entire table */ status = acpi_tb_get_table_body(&address, header, table_info); if (ACPI_FAILURE(status)) { goto cleanup; } *table_pointer = table_info->pointer; goto cleanup; } } } /* Did not find the table */ status = AE_NOT_EXIST; cleanup: if (rsdt_info->pointer) { acpi_os_unmap_memory(rsdt_info->pointer, (acpi_size) rsdt_info->pointer->length); } ACPI_MEM_FREE(rsdt_info); if (header) { ACPI_MEM_FREE(header); } if (table_info) { ACPI_MEM_FREE(table_info); } return_ACPI_STATUS(status); }
ACPI_STATUS AcpiTbAddTable ( ACPI_TABLE_DESC *TableDesc, UINT32 *TableIndex) { UINT32 i; ACPI_STATUS Status = AE_OK; ACPI_FUNCTION_TRACE (TbAddTable); if (!TableDesc->Pointer) { Status = AcpiTbVerifyTable (TableDesc); if (ACPI_FAILURE (Status) || !TableDesc->Pointer) { return_ACPI_STATUS (Status); } } /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((TableDesc->Pointer->Signature[0] != 0x00) && (!ACPI_COMPARE_NAME (TableDesc->Pointer->Signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP (TableDesc->Pointer->Signature, "OEM", 3))) { ACPI_BIOS_ERROR ((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), " "must be SSDT or OEMx", AcpiUtValidAcpiName (TableDesc->Pointer->Signature) ? TableDesc->Pointer->Signature : "????", *(UINT32 *) TableDesc->Pointer->Signature)); return_ACPI_STATUS (AE_BAD_SIGNATURE); } (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); /* Check if table is already registered */ for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) { if (!AcpiGbl_RootTableList.Tables[i].Pointer) { Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]); if (ACPI_FAILURE (Status) || !AcpiGbl_RootTableList.Tables[i].Pointer) { continue; } } /* * Check for a table match on the entire table length, * not just the header. */ if (TableDesc->Length != AcpiGbl_RootTableList.Tables[i].Length) { continue; } if (ACPI_MEMCMP (TableDesc->Pointer, AcpiGbl_RootTableList.Tables[i].Pointer, AcpiGbl_RootTableList.Tables[i].Length)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ /* * Table is already registered. * We can delete the table that was passed as a parameter. */ AcpiTbDeleteTable (TableDesc); *TableIndex = i; if (AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ Status = AE_ALREADY_EXISTS; goto Release; } else { /* Table was unloaded, allow it to be reloaded */ TableDesc->Pointer = AcpiGbl_RootTableList.Tables[i].Pointer; TableDesc->Address = AcpiGbl_RootTableList.Tables[i].Address; Status = AE_OK; goto PrintHeader; } } /* * ACPI Table Override: * Allow the host to override dynamically loaded tables. * NOTE: the table is fully mapped at this point, and the mapping will * be deleted by TbTableOverride if the table is actually overridden. */ (void) AcpiTbTableOverride (TableDesc->Pointer, TableDesc); /* Add the table to the global root table list */ Status = AcpiTbStoreTable (TableDesc->Address, TableDesc->Pointer, TableDesc->Length, TableDesc->Flags, TableIndex); if (ACPI_FAILURE (Status)) { goto Release; } PrintHeader: AcpiTbPrintTableHeader (TableDesc->Address, TableDesc->Pointer); Release: (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); return_ACPI_STATUS (Status); }
acpi_status acpi_tb_add_table(struct acpi_table_desc *table_desc, u32 *table_index) { u32 i; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(tb_add_table); if (!table_desc->pointer) { status = acpi_tb_verify_table(table_desc); if (ACPI_FAILURE(status) || !table_desc->pointer) { return_ACPI_STATUS(status); } } /* * Validate the incoming table signature. * * 1) Originally, we checked the table signature for "SSDT" or "PSDT". * 2) We added support for OEMx tables, signature "OEM". * 3) Valid tables were encountered with a null signature, so we just * gave up on validating the signature, (05/2008). * 4) We encountered non-AML tables such as the MADT, which caused * interpreter errors and kernel faults. So now, we once again allow * only "SSDT", "OEMx", and now, also a null signature. (05/2011). */ if ((table_desc->pointer->signature[0] != 0x00) && (!ACPI_COMPARE_NAME(table_desc->pointer->signature, ACPI_SIG_SSDT)) && (ACPI_STRNCMP(table_desc->pointer->signature, "OEM", 3))) { ACPI_ERROR((AE_INFO, "Table has invalid signature [%4.4s] (0x%8.8X), must be SSDT or OEMx", acpi_ut_valid_acpi_name(*(u32 *)table_desc-> pointer-> signature) ? table_desc-> pointer->signature : "????", *(u32 *)table_desc->pointer->signature)); return_ACPI_STATUS(AE_BAD_SIGNATURE); } (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); /* Check if table is already registered */ for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) { if (!acpi_gbl_root_table_list.tables[i].pointer) { status = acpi_tb_verify_table(&acpi_gbl_root_table_list. tables[i]); if (ACPI_FAILURE(status) || !acpi_gbl_root_table_list.tables[i].pointer) { continue; } } /* * Check for a table match on the entire table length, * not just the header. */ if (table_desc->length != acpi_gbl_root_table_list.tables[i].length) { continue; } if (ACPI_MEMCMP(table_desc->pointer, acpi_gbl_root_table_list.tables[i].pointer, acpi_gbl_root_table_list.tables[i].length)) { continue; } /* * Note: the current mechanism does not unregister a table if it is * dynamically unloaded. The related namespace entries are deleted, * but the table remains in the root table list. * * The assumption here is that the number of different tables that * will be loaded is actually small, and there is minimal overhead * in just keeping the table in case it is needed again. * * If this assumption changes in the future (perhaps on large * machines with many table load/unload operations), tables will * need to be unregistered when they are unloaded, and slots in the * root table list should be reused when empty. */ /* * Table is already registered. * We can delete the table that was passed as a parameter. */ acpi_tb_delete_table(table_desc); *table_index = i; if (acpi_gbl_root_table_list.tables[i]. flags & ACPI_TABLE_IS_LOADED) { /* Table is still loaded, this is an error */ status = AE_ALREADY_EXISTS; goto release; } else { /* Table was unloaded, allow it to be reloaded */ table_desc->pointer = acpi_gbl_root_table_list.tables[i].pointer; table_desc->address = acpi_gbl_root_table_list.tables[i].address; status = AE_OK; goto print_header; } } /* * ACPI Table Override: * Allow the host to override dynamically loaded tables. * NOTE: the table is fully mapped at this point, and the mapping will * be deleted by tb_table_override if the table is actually overridden. */ (void)acpi_tb_table_override(table_desc->pointer, table_desc); /* Add the table to the global root table list */ status = acpi_tb_store_table(table_desc->address, table_desc->pointer, table_desc->length, table_desc->flags, table_index); if (ACPI_FAILURE(status)) { goto release; } print_header: acpi_tb_print_table_header(table_desc->address, table_desc->pointer); release: (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); return_ACPI_STATUS(status); }