1 /****************************************************************************** 2 * 3 * Module Name: nsxfname - Public interfaces to the ACPI subsystem 4 * ACPI Namespace oriented interfaces 5 * 6 *****************************************************************************/ 7 8 /* 9 * Copyright (C) 2000 - 2008, Intel Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions, and the following disclaimer, 17 * without modification. 18 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19 * substantially similar to the "NO WARRANTY" disclaimer below 20 * ("Disclaimer") and any redistribution must be conditioned upon 21 * including a substantially similar Disclaimer requirement for further 22 * binary redistribution. 23 * 3. Neither the names of the above-listed copyright holders nor the names 24 * of any contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * Alternatively, this software may be distributed under the terms of the 28 * GNU General Public License ("GPL") version 2 as published by the Free 29 * Software Foundation. 30 * 31 * NO WARRANTY 32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42 * POSSIBILITY OF SUCH DAMAGES. 43 */ 44 45 #include <acpi/acpi.h> 46 #include "accommon.h" 47 #include "acnamesp.h" 48 #include "acparser.h" 49 #include "amlcode.h" 50 51 #define _COMPONENT ACPI_NAMESPACE 52 ACPI_MODULE_NAME("nsxfname") 53 54 /****************************************************************************** 55 * 56 * FUNCTION: acpi_get_handle 57 * 58 * PARAMETERS: Parent - Object to search under (search scope). 59 * Pathname - Pointer to an asciiz string containing the 60 * name 61 * ret_handle - Where the return handle is returned 62 * 63 * RETURN: Status 64 * 65 * DESCRIPTION: This routine will search for a caller specified name in the 66 * name space. The caller can restrict the search region by 67 * specifying a non NULL parent. The parent value is itself a 68 * namespace handle. 69 * 70 ******************************************************************************/ 71 acpi_status 72 acpi_get_handle(acpi_handle parent, 73 acpi_string pathname, acpi_handle * ret_handle) 74 { 75 acpi_status status; 76 struct acpi_namespace_node *node = NULL; 77 struct acpi_namespace_node *prefix_node = NULL; 78 79 ACPI_FUNCTION_ENTRY(); 80 81 /* Parameter Validation */ 82 83 if (!ret_handle || !pathname) { 84 return (AE_BAD_PARAMETER); 85 } 86 87 /* Convert a parent handle to a prefix node */ 88 89 if (parent) { 90 prefix_node = acpi_ns_map_handle_to_node(parent); 91 if (!prefix_node) { 92 return (AE_BAD_PARAMETER); 93 } 94 } 95 96 /* 97 * Valid cases are: 98 * 1) Fully qualified pathname 99 * 2) Parent + Relative pathname 100 * 101 * Error for <null Parent + relative path> 102 */ 103 if (acpi_ns_valid_root_prefix(pathname[0])) { 104 105 /* Pathname is fully qualified (starts with '\') */ 106 107 /* Special case for root-only, since we can't search for it */ 108 109 if (!ACPI_STRCMP(pathname, ACPI_NS_ROOT_PATH)) { 110 *ret_handle = 111 acpi_ns_convert_entry_to_handle(acpi_gbl_root_node); 112 return (AE_OK); 113 } 114 } else if (!prefix_node) { 115 116 /* Relative path with null prefix is disallowed */ 117 118 return (AE_BAD_PARAMETER); 119 } 120 121 /* Find the Node and convert to a handle */ 122 123 status = 124 acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node); 125 if (ACPI_SUCCESS(status)) { 126 *ret_handle = acpi_ns_convert_entry_to_handle(node); 127 } 128 129 return (status); 130 } 131 132 ACPI_EXPORT_SYMBOL(acpi_get_handle) 133 134 /****************************************************************************** 135 * 136 * FUNCTION: acpi_get_name 137 * 138 * PARAMETERS: Handle - Handle to be converted to a pathname 139 * name_type - Full pathname or single segment 140 * Buffer - Buffer for returned path 141 * 142 * RETURN: Pointer to a string containing the fully qualified Name. 143 * 144 * DESCRIPTION: This routine returns the fully qualified name associated with 145 * the Handle parameter. This and the acpi_pathname_to_handle are 146 * complementary functions. 147 * 148 ******************************************************************************/ 149 acpi_status 150 acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) 151 { 152 acpi_status status; 153 struct acpi_namespace_node *node; 154 155 /* Parameter validation */ 156 157 if (name_type > ACPI_NAME_TYPE_MAX) { 158 return (AE_BAD_PARAMETER); 159 } 160 161 status = acpi_ut_validate_buffer(buffer); 162 if (ACPI_FAILURE(status)) { 163 return (status); 164 } 165 166 if (name_type == ACPI_FULL_PATHNAME) { 167 168 /* Get the full pathname (From the namespace root) */ 169 170 status = acpi_ns_handle_to_pathname(handle, buffer); 171 return (status); 172 } 173 174 /* 175 * Wants the single segment ACPI name. 176 * Validate handle and convert to a namespace Node 177 */ 178 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 179 if (ACPI_FAILURE(status)) { 180 return (status); 181 } 182 183 node = acpi_ns_map_handle_to_node(handle); 184 if (!node) { 185 status = AE_BAD_PARAMETER; 186 goto unlock_and_exit; 187 } 188 189 /* Validate/Allocate/Clear caller buffer */ 190 191 status = acpi_ut_initialize_buffer(buffer, ACPI_PATH_SEGMENT_LENGTH); 192 if (ACPI_FAILURE(status)) { 193 goto unlock_and_exit; 194 } 195 196 /* Just copy the ACPI name from the Node and zero terminate it */ 197 198 ACPI_STRNCPY(buffer->pointer, acpi_ut_get_node_name(node), 199 ACPI_NAME_SIZE); 200 ((char *)buffer->pointer)[ACPI_NAME_SIZE] = 0; 201 status = AE_OK; 202 203 unlock_and_exit: 204 205 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 206 return (status); 207 } 208 209 ACPI_EXPORT_SYMBOL(acpi_get_name) 210 211 /****************************************************************************** 212 * 213 * FUNCTION: acpi_get_object_info 214 * 215 * PARAMETERS: Handle - Object Handle 216 * Buffer - Where the info is returned 217 * 218 * RETURN: Status 219 * 220 * DESCRIPTION: Returns information about an object as gleaned from the 221 * namespace node and possibly by running several standard 222 * control methods (Such as in the case of a device.) 223 * 224 ******************************************************************************/ 225 acpi_status 226 acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) 227 { 228 acpi_status status; 229 struct acpi_namespace_node *node; 230 struct acpi_device_info *info; 231 struct acpi_device_info *return_info; 232 struct acpi_compatible_id_list *cid_list = NULL; 233 acpi_size size; 234 235 /* Parameter validation */ 236 237 if (!handle || !buffer) { 238 return (AE_BAD_PARAMETER); 239 } 240 241 status = acpi_ut_validate_buffer(buffer); 242 if (ACPI_FAILURE(status)) { 243 return (status); 244 } 245 246 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); 247 if (!info) { 248 return (AE_NO_MEMORY); 249 } 250 251 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 252 if (ACPI_FAILURE(status)) { 253 goto cleanup; 254 } 255 256 node = acpi_ns_map_handle_to_node(handle); 257 if (!node) { 258 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 259 status = AE_BAD_PARAMETER; 260 goto cleanup; 261 } 262 263 /* Init return structure */ 264 265 size = sizeof(struct acpi_device_info); 266 267 info->type = node->type; 268 info->name = node->name.integer; 269 info->valid = 0; 270 271 if (node->type == ACPI_TYPE_METHOD) { 272 info->param_count = node->object->method.param_count; 273 } 274 275 status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 276 if (ACPI_FAILURE(status)) { 277 goto cleanup; 278 } 279 280 /* If not a device, we are all done */ 281 282 if (info->type == ACPI_TYPE_DEVICE) { 283 /* 284 * Get extra info for ACPI Devices objects only: 285 * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. 286 * 287 * Note: none of these methods are required, so they may or may 288 * not be present for this device. The Info->Valid bitfield is used 289 * to indicate which methods were found and ran successfully. 290 */ 291 292 /* Execute the Device._HID method */ 293 294 status = acpi_ut_execute_HID(node, &info->hardware_id); 295 if (ACPI_SUCCESS(status)) { 296 info->valid |= ACPI_VALID_HID; 297 } 298 299 /* Execute the Device._UID method */ 300 301 status = acpi_ut_execute_UID(node, &info->unique_id); 302 if (ACPI_SUCCESS(status)) { 303 info->valid |= ACPI_VALID_UID; 304 } 305 306 /* Execute the Device._CID method */ 307 308 status = acpi_ut_execute_CID(node, &cid_list); 309 if (ACPI_SUCCESS(status)) { 310 size += cid_list->size; 311 info->valid |= ACPI_VALID_CID; 312 } 313 314 /* Execute the Device._STA method */ 315 316 status = acpi_ut_execute_STA(node, &info->current_status); 317 if (ACPI_SUCCESS(status)) { 318 info->valid |= ACPI_VALID_STA; 319 } 320 321 /* Execute the Device._ADR method */ 322 323 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, 324 &info->address); 325 if (ACPI_SUCCESS(status)) { 326 info->valid |= ACPI_VALID_ADR; 327 } 328 329 /* Execute the Device._sx_d methods */ 330 331 status = acpi_ut_execute_sxds(node, info->highest_dstates); 332 if (ACPI_SUCCESS(status)) { 333 info->valid |= ACPI_VALID_SXDS; 334 } 335 } 336 337 /* Validate/Allocate/Clear caller buffer */ 338 339 status = acpi_ut_initialize_buffer(buffer, size); 340 if (ACPI_FAILURE(status)) { 341 goto cleanup; 342 } 343 344 /* Populate the return buffer */ 345 346 return_info = buffer->pointer; 347 ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); 348 349 if (cid_list) { 350 ACPI_MEMCPY(&return_info->compatibility_id, cid_list, 351 cid_list->size); 352 } 353 354 cleanup: 355 ACPI_FREE(info); 356 if (cid_list) { 357 ACPI_FREE(cid_list); 358 } 359 return (status); 360 } 361 362 ACPI_EXPORT_SYMBOL(acpi_get_object_info) 363 364 /****************************************************************************** 365 * 366 * FUNCTION: acpi_install_method 367 * 368 * PARAMETERS: Buffer - An ACPI table containing one control method 369 * 370 * RETURN: Status 371 * 372 * DESCRIPTION: Install a control method into the namespace. If the method 373 * name already exists in the namespace, it is overwritten. The 374 * input buffer must contain a valid DSDT or SSDT containing a 375 * single control method. 376 * 377 ******************************************************************************/ 378 acpi_status acpi_install_method(u8 *buffer) 379 { 380 struct acpi_table_header *table = 381 ACPI_CAST_PTR(struct acpi_table_header, buffer); 382 u8 *aml_buffer; 383 u8 *aml_start; 384 char *path; 385 struct acpi_namespace_node *node; 386 union acpi_operand_object *method_obj; 387 struct acpi_parse_state parser_state; 388 u32 aml_length; 389 u16 opcode; 390 u8 method_flags; 391 acpi_status status; 392 393 /* Parameter validation */ 394 395 if (!buffer) { 396 return AE_BAD_PARAMETER; 397 } 398 399 /* Table must be a DSDT or SSDT */ 400 401 if (!ACPI_COMPARE_NAME(table->signature, ACPI_SIG_DSDT) && 402 !ACPI_COMPARE_NAME(table->signature, ACPI_SIG_SSDT)) { 403 return AE_BAD_HEADER; 404 } 405 406 /* First AML opcode in the table must be a control method */ 407 408 parser_state.aml = buffer + sizeof(struct acpi_table_header); 409 opcode = acpi_ps_peek_opcode(&parser_state); 410 if (opcode != AML_METHOD_OP) { 411 return AE_BAD_PARAMETER; 412 } 413 414 /* Extract method information from the raw AML */ 415 416 parser_state.aml += acpi_ps_get_opcode_size(opcode); 417 parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state); 418 path = acpi_ps_get_next_namestring(&parser_state); 419 method_flags = *parser_state.aml++; 420 aml_start = parser_state.aml; 421 aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start); 422 423 /* 424 * Allocate resources up-front. We don't want to have to delete a new 425 * node from the namespace if we cannot allocate memory. 426 */ 427 aml_buffer = ACPI_ALLOCATE(aml_length); 428 if (!aml_buffer) { 429 return AE_NO_MEMORY; 430 } 431 432 method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); 433 if (!method_obj) { 434 ACPI_FREE(aml_buffer); 435 return AE_NO_MEMORY; 436 } 437 438 /* Lock namespace for acpi_ns_lookup, we may be creating a new node */ 439 440 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 441 if (ACPI_FAILURE(status)) { 442 goto error_exit; 443 } 444 445 /* The lookup either returns an existing node or creates a new one */ 446 447 status = 448 acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1, 449 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, 450 NULL, &node); 451 452 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 453 454 if (ACPI_FAILURE(status)) { /* ns_lookup */ 455 if (status != AE_ALREADY_EXISTS) { 456 goto error_exit; 457 } 458 459 /* Node existed previously, make sure it is a method node */ 460 461 if (node->type != ACPI_TYPE_METHOD) { 462 status = AE_TYPE; 463 goto error_exit; 464 } 465 } 466 467 /* Copy the method AML to the local buffer */ 468 469 ACPI_MEMCPY(aml_buffer, aml_start, aml_length); 470 471 /* Initialize the method object with the new method's information */ 472 473 method_obj->method.aml_start = aml_buffer; 474 method_obj->method.aml_length = aml_length; 475 476 method_obj->method.param_count = (u8) 477 (method_flags & AML_METHOD_ARG_COUNT); 478 479 method_obj->method.method_flags = (u8) 480 (method_flags & ~AML_METHOD_ARG_COUNT); 481 482 if (method_flags & AML_METHOD_SERIALIZED) { 483 method_obj->method.sync_level = (u8) 484 ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4); 485 } 486 487 /* 488 * Now that it is complete, we can attach the new method object to 489 * the method Node (detaches/deletes any existing object) 490 */ 491 status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD); 492 493 /* 494 * Flag indicates AML buffer is dynamic, must be deleted later. 495 * Must be set only after attach above. 496 */ 497 node->flags |= ANOBJ_ALLOCATED_BUFFER; 498 499 /* Remove local reference to the method object */ 500 501 acpi_ut_remove_reference(method_obj); 502 return status; 503 504 error_exit: 505 506 ACPI_FREE(aml_buffer); 507 ACPI_FREE(method_obj); 508 return status; 509 } 510 ACPI_EXPORT_SYMBOL(acpi_install_method) 511