linux/drivers/acpi/namespace/nsutils.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
   4 *                        parents and siblings and Scope manipulation
   5 *
   6 *****************************************************************************/
   7
   8/*
   9 * Copyright (C) 2000 - 2007, R. Byron Moore
  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 <acpi/acnamesp.h>
  47#include <acpi/amlcode.h>
  48#include <acpi/actables.h>
  49
  50#define _COMPONENT          ACPI_NAMESPACE
  51ACPI_MODULE_NAME("nsutils")
  52
  53/* Local prototypes */
  54static u8 acpi_ns_valid_path_separator(char sep);
  55
  56#ifdef ACPI_OBSOLETE_FUNCTIONS
  57acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
  58#endif
  59
  60/*******************************************************************************
  61 *
  62 * FUNCTION:    acpi_ns_report_error
  63 *
  64 * PARAMETERS:  module_name         - Caller's module name (for error output)
  65 *              line_number         - Caller's line number (for error output)
  66 *              internal_name       - Name or path of the namespace node
  67 *              lookup_status       - Exception code from NS lookup
  68 *
  69 * RETURN:      None
  70 *
  71 * DESCRIPTION: Print warning message with full pathname
  72 *
  73 ******************************************************************************/
  74
  75void
  76acpi_ns_report_error(char *module_name,
  77                     u32 line_number,
  78                     char *internal_name, acpi_status lookup_status)
  79{
  80        acpi_status status;
  81        u32 bad_name;
  82        char *name = NULL;
  83
  84        acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
  85
  86        if (lookup_status == AE_BAD_CHARACTER) {
  87
  88                /* There is a non-ascii character in the name */
  89
  90                ACPI_MOVE_32_TO_32(&bad_name, internal_name);
  91                acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name);
  92        } else {
  93                /* Convert path to external format */
  94
  95                status = acpi_ns_externalize_name(ACPI_UINT32_MAX,
  96                                                  internal_name, NULL, &name);
  97
  98                /* Print target name */
  99
 100                if (ACPI_SUCCESS(status)) {
 101                        acpi_os_printf("[%s]", name);
 102                } else {
 103                        acpi_os_printf("[COULD NOT EXTERNALIZE NAME]");
 104                }
 105
 106                if (name) {
 107                        ACPI_FREE(name);
 108                }
 109        }
 110
 111        acpi_os_printf(" Namespace lookup failure, %s\n",
 112                       acpi_format_exception(lookup_status));
 113}
 114
 115/*******************************************************************************
 116 *
 117 * FUNCTION:    acpi_ns_report_method_error
 118 *
 119 * PARAMETERS:  module_name         - Caller's module name (for error output)
 120 *              line_number         - Caller's line number (for error output)
 121 *              Message             - Error message to use on failure
 122 *              prefix_node         - Prefix relative to the path
 123 *              Path                - Path to the node (optional)
 124 *              method_status       - Execution status
 125 *
 126 * RETURN:      None
 127 *
 128 * DESCRIPTION: Print warning message with full pathname
 129 *
 130 ******************************************************************************/
 131
 132void
 133acpi_ns_report_method_error(char *module_name,
 134                            u32 line_number,
 135                            char *message,
 136                            struct acpi_namespace_node *prefix_node,
 137                            char *path, acpi_status method_status)
 138{
 139        acpi_status status;
 140        struct acpi_namespace_node *node = prefix_node;
 141
 142        acpi_os_printf("ACPI Error (%s-%04d): ", module_name, line_number);
 143
 144        if (path) {
 145                status =
 146                    acpi_ns_get_node(prefix_node, path, ACPI_NS_NO_UPSEARCH,
 147                                     &node);
 148                if (ACPI_FAILURE(status)) {
 149                        acpi_os_printf("[Could not get node by pathname]");
 150                }
 151        }
 152
 153        acpi_ns_print_node_pathname(node, message);
 154        acpi_os_printf(", %s\n", acpi_format_exception(method_status));
 155}
 156
 157/*******************************************************************************
 158 *
 159 * FUNCTION:    acpi_ns_print_node_pathname
 160 *
 161 * PARAMETERS:  Node            - Object
 162 *              Message         - Prefix message
 163 *
 164 * DESCRIPTION: Print an object's full namespace pathname
 165 *              Manages allocation/freeing of a pathname buffer
 166 *
 167 ******************************************************************************/
 168
 169void
 170acpi_ns_print_node_pathname(struct acpi_namespace_node *node, char *message)
 171{
 172        struct acpi_buffer buffer;
 173        acpi_status status;
 174
 175        if (!node) {
 176                acpi_os_printf("[NULL NAME]");
 177                return;
 178        }
 179
 180        /* Convert handle to full pathname and print it (with supplied message) */
 181
 182        buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
 183
 184        status = acpi_ns_handle_to_pathname(node, &buffer);
 185        if (ACPI_SUCCESS(status)) {
 186                if (message) {
 187                        acpi_os_printf("%s ", message);
 188                }
 189
 190                acpi_os_printf("[%s] (Node %p)", (char *)buffer.pointer, node);
 191                ACPI_FREE(buffer.pointer);
 192        }
 193}
 194
 195/*******************************************************************************
 196 *
 197 * FUNCTION:    acpi_ns_valid_root_prefix
 198 *
 199 * PARAMETERS:  Prefix          - Character to be checked
 200 *
 201 * RETURN:      TRUE if a valid prefix
 202 *
 203 * DESCRIPTION: Check if a character is a valid ACPI Root prefix
 204 *
 205 ******************************************************************************/
 206
 207u8 acpi_ns_valid_root_prefix(char prefix)
 208{
 209
 210        return ((u8) (prefix == '\\'));
 211}
 212
 213/*******************************************************************************
 214 *
 215 * FUNCTION:    acpi_ns_valid_path_separator
 216 *
 217 * PARAMETERS:  Sep         - Character to be checked
 218 *
 219 * RETURN:      TRUE if a valid path separator
 220 *
 221 * DESCRIPTION: Check if a character is a valid ACPI path separator
 222 *
 223 ******************************************************************************/
 224
 225static u8 acpi_ns_valid_path_separator(char sep)
 226{
 227
 228        return ((u8) (sep == '.'));
 229}
 230
 231/*******************************************************************************
 232 *
 233 * FUNCTION:    acpi_ns_get_type
 234 *
 235 * PARAMETERS:  Node        - Parent Node to be examined
 236 *
 237 * RETURN:      Type field from Node whose handle is passed
 238 *
 239 * DESCRIPTION: Return the type of a Namespace node
 240 *
 241 ******************************************************************************/
 242
 243acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
 244{
 245        ACPI_FUNCTION_TRACE(ns_get_type);
 246
 247        if (!node) {
 248                ACPI_WARNING((AE_INFO, "Null Node parameter"));
 249                return_UINT32(ACPI_TYPE_ANY);
 250        }
 251
 252        return_UINT32((acpi_object_type) node->type);
 253}
 254
 255/*******************************************************************************
 256 *
 257 * FUNCTION:    acpi_ns_local
 258 *
 259 * PARAMETERS:  Type        - A namespace object type
 260 *
 261 * RETURN:      LOCAL if names must be found locally in objects of the
 262 *              passed type, 0 if enclosing scopes should be searched
 263 *
 264 * DESCRIPTION: Returns scope rule for the given object type.
 265 *
 266 ******************************************************************************/
 267
 268u32 acpi_ns_local(acpi_object_type type)
 269{
 270        ACPI_FUNCTION_TRACE(ns_local);
 271
 272        if (!acpi_ut_valid_object_type(type)) {
 273
 274                /* Type code out of range  */
 275
 276                ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
 277                return_UINT32(ACPI_NS_NORMAL);
 278        }
 279
 280        return_UINT32((u32) acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
 281}
 282
 283/*******************************************************************************
 284 *
 285 * FUNCTION:    acpi_ns_get_internal_name_length
 286 *
 287 * PARAMETERS:  Info            - Info struct initialized with the
 288 *                                external name pointer.
 289 *
 290 * RETURN:      None
 291 *
 292 * DESCRIPTION: Calculate the length of the internal (AML) namestring
 293 *              corresponding to the external (ASL) namestring.
 294 *
 295 ******************************************************************************/
 296
 297void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
 298{
 299        char *next_external_char;
 300        u32 i;
 301
 302        ACPI_FUNCTION_ENTRY();
 303
 304        next_external_char = info->external_name;
 305        info->num_carats = 0;
 306        info->num_segments = 0;
 307        info->fully_qualified = FALSE;
 308
 309        /*
 310         * For the internal name, the required length is 4 bytes per segment, plus
 311         * 1 each for root_prefix, multi_name_prefix_op, segment count, trailing null
 312         * (which is not really needed, but no there's harm in putting it there)
 313         *
 314         * strlen() + 1 covers the first name_seg, which has no path separator
 315         */
 316        if (acpi_ns_valid_root_prefix(next_external_char[0])) {
 317                info->fully_qualified = TRUE;
 318                next_external_char++;
 319        } else {
 320                /*
 321                 * Handle Carat prefixes
 322                 */
 323                while (*next_external_char == '^') {
 324                        info->num_carats++;
 325                        next_external_char++;
 326                }
 327        }
 328
 329        /*
 330         * Determine the number of ACPI name "segments" by counting the number of
 331         * path separators within the string. Start with one segment since the
 332         * segment count is [(# separators) + 1], and zero separators is ok.
 333         */
 334        if (*next_external_char) {
 335                info->num_segments = 1;
 336                for (i = 0; next_external_char[i]; i++) {
 337                        if (acpi_ns_valid_path_separator(next_external_char[i])) {
 338                                info->num_segments++;
 339                        }
 340                }
 341        }
 342
 343        info->length = (ACPI_NAME_SIZE * info->num_segments) +
 344            4 + info->num_carats;
 345
 346        info->next_external_char = next_external_char;
 347}
 348
 349/*******************************************************************************
 350 *
 351 * FUNCTION:    acpi_ns_build_internal_name
 352 *
 353 * PARAMETERS:  Info            - Info struct fully initialized
 354 *
 355 * RETURN:      Status
 356 *
 357 * DESCRIPTION: Construct the internal (AML) namestring
 358 *              corresponding to the external (ASL) namestring.
 359 *
 360 ******************************************************************************/
 361
 362acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
 363{
 364        u32 num_segments = info->num_segments;
 365        char *internal_name = info->internal_name;
 366        char *external_name = info->next_external_char;
 367        char *result = NULL;
 368        acpi_native_uint i;
 369
 370        ACPI_FUNCTION_TRACE(ns_build_internal_name);
 371
 372        /* Setup the correct prefixes, counts, and pointers */
 373
 374        if (info->fully_qualified) {
 375                internal_name[0] = '\\';
 376
 377                if (num_segments <= 1) {
 378                        result = &internal_name[1];
 379                } else if (num_segments == 2) {
 380                        internal_name[1] = AML_DUAL_NAME_PREFIX;
 381                        result = &internal_name[2];
 382                } else {
 383                        internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
 384                        internal_name[2] = (char)num_segments;
 385                        result = &internal_name[3];
 386                }
 387        } else {
 388                /*
 389                 * Not fully qualified.
 390                 * Handle Carats first, then append the name segments
 391                 */
 392                i = 0;
 393                if (info->num_carats) {
 394                        for (i = 0; i < info->num_carats; i++) {
 395                                internal_name[i] = '^';
 396                        }
 397                }
 398
 399                if (num_segments <= 1) {
 400                        result = &internal_name[i];
 401                } else if (num_segments == 2) {
 402                        internal_name[i] = AML_DUAL_NAME_PREFIX;
 403                        result = &internal_name[(acpi_native_uint) (i + 1)];
 404                } else {
 405                        internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
 406                        internal_name[(acpi_native_uint) (i + 1)] =
 407                            (char)num_segments;
 408                        result = &internal_name[(acpi_native_uint) (i + 2)];
 409                }
 410        }
 411
 412        /* Build the name (minus path separators) */
 413
 414        for (; num_segments; num_segments--) {
 415                for (i = 0; i < ACPI_NAME_SIZE; i++) {
 416                        if (acpi_ns_valid_path_separator(*external_name) ||
 417                            (*external_name == 0)) {
 418
 419                                /* Pad the segment with underscore(s) if segment is short */
 420
 421                                result[i] = '_';
 422                        } else {
 423                                /* Convert the character to uppercase and save it */
 424
 425                                result[i] =
 426                                    (char)ACPI_TOUPPER((int)*external_name);
 427                                external_name++;
 428                        }
 429                }
 430
 431                /* Now we must have a path separator, or the pathname is bad */
 432
 433                if (!acpi_ns_valid_path_separator(*external_name) &&
 434                    (*external_name != 0)) {
 435                        return_ACPI_STATUS(AE_BAD_PARAMETER);
 436                }
 437
 438                /* Move on the next segment */
 439
 440                external_name++;
 441                result += ACPI_NAME_SIZE;
 442        }
 443
 444        /* Terminate the string */
 445
 446        *result = 0;
 447
 448        if (info->fully_qualified) {
 449                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 450                                  "Returning [%p] (abs) \"\\%s\"\n",
 451                                  internal_name, internal_name));
 452        } else {
 453                ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
 454                                  internal_name, internal_name));
 455        }
 456
 457        return_ACPI_STATUS(AE_OK);
 458}
 459
 460/*******************************************************************************
 461 *
 462 * FUNCTION:    acpi_ns_internalize_name
 463 *
 464 * PARAMETERS:  *external_name          - External representation of name
 465 *              **Converted Name        - Where to return the resulting
 466 *                                        internal represention of the name
 467 *
 468 * RETURN:      Status
 469 *
 470 * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
 471 *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
 472 *
 473 *******************************************************************************/
 474
 475acpi_status acpi_ns_internalize_name(char *external_name, char **converted_name)
 476{
 477        char *internal_name;
 478        struct acpi_namestring_info info;
 479        acpi_status status;
 480
 481        ACPI_FUNCTION_TRACE(ns_internalize_name);
 482
 483        if ((!external_name) || (*external_name == 0) || (!converted_name)) {
 484                return_ACPI_STATUS(AE_BAD_PARAMETER);
 485        }
 486
 487        /* Get the length of the new internal name */
 488
 489        info.external_name = external_name;
 490        acpi_ns_get_internal_name_length(&info);
 491
 492        /* We need a segment to store the internal  name */
 493
 494        internal_name = ACPI_ALLOCATE_ZEROED(info.length);
 495        if (!internal_name) {
 496                return_ACPI_STATUS(AE_NO_MEMORY);
 497        }
 498
 499        /* Build the name */
 500
 501        info.internal_name = internal_name;
 502        status = acpi_ns_build_internal_name(&info);
 503        if (ACPI_FAILURE(status)) {
 504                ACPI_FREE(internal_name);
 505                return_ACPI_STATUS(status);
 506        }
 507
 508        *converted_name = internal_name;
 509        return_ACPI_STATUS(AE_OK);
 510}
 511
 512/*******************************************************************************
 513 *
 514 * FUNCTION:    acpi_ns_externalize_name
 515 *
 516 * PARAMETERS:  internal_name_length - Lenth of the internal name below
 517 *              internal_name       - Internal representation of name
 518 *              converted_name_length - Where the length is returned
 519 *              converted_name      - Where the resulting external name
 520 *                                    is returned
 521 *
 522 * RETURN:      Status
 523 *
 524 * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
 525 *              to its external (printable) form (e.g. "\_PR_.CPU0")
 526 *
 527 ******************************************************************************/
 528
 529acpi_status
 530acpi_ns_externalize_name(u32 internal_name_length,
 531                         char *internal_name,
 532                         u32 * converted_name_length, char **converted_name)
 533{
 534        acpi_native_uint names_index = 0;
 535        acpi_native_uint num_segments = 0;
 536        acpi_native_uint required_length;
 537        acpi_native_uint prefix_length = 0;
 538        acpi_native_uint i = 0;
 539        acpi_native_uint j = 0;
 540
 541        ACPI_FUNCTION_TRACE(ns_externalize_name);
 542
 543        if (!internal_name_length || !internal_name || !converted_name) {
 544                return_ACPI_STATUS(AE_BAD_PARAMETER);
 545        }
 546
 547        /*
 548         * Check for a prefix (one '\' | one or more '^').
 549         */
 550        switch (internal_name[0]) {
 551        case '\\':
 552                prefix_length = 1;
 553                break;
 554
 555        case '^':
 556                for (i = 0; i < internal_name_length; i++) {
 557                        if (internal_name[i] == '^') {
 558                                prefix_length = i + 1;
 559                        } else {
 560                                break;
 561                        }
 562                }
 563
 564                if (i == internal_name_length) {
 565                        prefix_length = i;
 566                }
 567
 568                break;
 569
 570        default:
 571                break;
 572        }
 573
 574        /*
 575         * Check for object names.  Note that there could be 0-255 of these
 576         * 4-byte elements.
 577         */
 578        if (prefix_length < internal_name_length) {
 579                switch (internal_name[prefix_length]) {
 580                case AML_MULTI_NAME_PREFIX_OP:
 581
 582                        /* <count> 4-byte names */
 583
 584                        names_index = prefix_length + 2;
 585                        num_segments = (acpi_native_uint) (u8)
 586                            internal_name[(acpi_native_uint)
 587                                          (prefix_length + 1)];
 588                        break;
 589
 590                case AML_DUAL_NAME_PREFIX:
 591
 592                        /* Two 4-byte names */
 593
 594                        names_index = prefix_length + 1;
 595                        num_segments = 2;
 596                        break;
 597
 598                case 0:
 599
 600                        /* null_name */
 601
 602                        names_index = 0;
 603                        num_segments = 0;
 604                        break;
 605
 606                default:
 607
 608                        /* one 4-byte name */
 609
 610                        names_index = prefix_length;
 611                        num_segments = 1;
 612                        break;
 613                }
 614        }
 615
 616        /*
 617         * Calculate the length of converted_name, which equals the length
 618         * of the prefix, length of all object names, length of any required
 619         * punctuation ('.') between object names, plus the NULL terminator.
 620         */
 621        required_length = prefix_length + (4 * num_segments) +
 622            ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
 623
 624        /*
 625         * Check to see if we're still in bounds.  If not, there's a problem
 626         * with internal_name (invalid format).
 627         */
 628        if (required_length > internal_name_length) {
 629                ACPI_ERROR((AE_INFO, "Invalid internal name"));
 630                return_ACPI_STATUS(AE_BAD_PATHNAME);
 631        }
 632
 633        /*
 634         * Build converted_name
 635         */
 636        *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
 637        if (!(*converted_name)) {
 638                return_ACPI_STATUS(AE_NO_MEMORY);
 639        }
 640
 641        j = 0;
 642
 643        for (i = 0; i < prefix_length; i++) {
 644                (*converted_name)[j++] = internal_name[i];
 645        }
 646
 647        if (num_segments > 0) {
 648                for (i = 0; i < num_segments; i++) {
 649                        if (i > 0) {
 650                                (*converted_name)[j++] = '.';
 651                        }
 652
 653                        (*converted_name)[j++] = internal_name[names_index++];
 654                        (*converted_name)[j++] = internal_name[names_index++];
 655                        (*converted_name)[j++] = internal_name[names_index++];
 656                        (*converted_name)[j++] = internal_name[names_index++];
 657                }
 658        }
 659
 660        if (converted_name_length) {
 661                *converted_name_length = (u32) required_length;
 662        }
 663
 664        return_ACPI_STATUS(AE_OK);
 665}
 666
 667/*******************************************************************************
 668 *
 669 * FUNCTION:    acpi_ns_map_handle_to_node
 670 *
 671 * PARAMETERS:  Handle          - Handle to be converted to an Node
 672 *
 673 * RETURN:      A Name table entry pointer
 674 *
 675 * DESCRIPTION: Convert a namespace handle to a real Node
 676 *
 677 * Note: Real integer handles would allow for more verification
 678 *       and keep all pointers within this subsystem - however this introduces
 679 *       more (and perhaps unnecessary) overhead.
 680 *
 681 ******************************************************************************/
 682
 683struct acpi_namespace_node *acpi_ns_map_handle_to_node(acpi_handle handle)
 684{
 685
 686        ACPI_FUNCTION_ENTRY();
 687
 688        /*
 689         * Simple implementation
 690         */
 691        if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
 692                return (acpi_gbl_root_node);
 693        }
 694
 695        /* We can at least attempt to verify the handle */
 696
 697        if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
 698                return (NULL);
 699        }
 700
 701        return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
 702}
 703
 704/*******************************************************************************
 705 *
 706 * FUNCTION:    acpi_ns_convert_entry_to_handle
 707 *
 708 * PARAMETERS:  Node          - Node to be converted to a Handle
 709 *
 710 * RETURN:      A user handle
 711 *
 712 * DESCRIPTION: Convert a real Node to a namespace handle
 713 *
 714 ******************************************************************************/
 715
 716acpi_handle acpi_ns_convert_entry_to_handle(struct acpi_namespace_node *node)
 717{
 718
 719        /*
 720         * Simple implementation for now;
 721         */
 722        return ((acpi_handle) node);
 723
 724/* Example future implementation ---------------------
 725
 726        if (!Node)
 727        {
 728                return (NULL);
 729        }
 730
 731        if (Node == acpi_gbl_root_node)
 732        {
 733                return (ACPI_ROOT_OBJECT);
 734        }
 735
 736        return ((acpi_handle) Node);
 737------------------------------------------------------*/
 738}
 739
 740/*******************************************************************************
 741 *
 742 * FUNCTION:    acpi_ns_terminate
 743 *
 744 * PARAMETERS:  none
 745 *
 746 * RETURN:      none
 747 *
 748 * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
 749 *
 750 ******************************************************************************/
 751
 752void acpi_ns_terminate(void)
 753{
 754        union acpi_operand_object *obj_desc;
 755
 756        ACPI_FUNCTION_TRACE(ns_terminate);
 757
 758        /*
 759         * 1) Free the entire namespace -- all nodes and objects
 760         *
 761         * Delete all object descriptors attached to namepsace nodes
 762         */
 763        acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
 764
 765        /* Detach any objects attached to the root */
 766
 767        obj_desc = acpi_ns_get_attached_object(acpi_gbl_root_node);
 768        if (obj_desc) {
 769                acpi_ns_detach_object(acpi_gbl_root_node);
 770        }
 771
 772        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
 773        return_VOID;
 774}
 775
 776/*******************************************************************************
 777 *
 778 * FUNCTION:    acpi_ns_opens_scope
 779 *
 780 * PARAMETERS:  Type        - A valid namespace type
 781 *
 782 * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
 783 *              to the ACPI specification, else 0
 784 *
 785 ******************************************************************************/
 786
 787u32 acpi_ns_opens_scope(acpi_object_type type)
 788{
 789        ACPI_FUNCTION_TRACE_STR(ns_opens_scope, acpi_ut_get_type_name(type));
 790
 791        if (!acpi_ut_valid_object_type(type)) {
 792
 793                /* type code out of range  */
 794
 795                ACPI_WARNING((AE_INFO, "Invalid Object Type %X", type));
 796                return_UINT32(ACPI_NS_NORMAL);
 797        }
 798
 799        return_UINT32(((u32) acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
 800}
 801
 802/*******************************************************************************
 803 *
 804 * FUNCTION:    acpi_ns_get_node
 805 *
 806 * PARAMETERS:  *Pathname   - Name to be found, in external (ASL) format. The
 807 *                            \ (backslash) and ^ (carat) prefixes, and the
 808 *                            . (period) to separate segments are supported.
 809 *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
 810 *                            root of the name space.  If Name is fully
 811 *                            qualified (first s8 is '\'), the passed value
 812 *                            of Scope will not be accessed.
 813 *              Flags       - Used to indicate whether to perform upsearch or
 814 *                            not.
 815 *              return_node - Where the Node is returned
 816 *
 817 * DESCRIPTION: Look up a name relative to a given scope and return the
 818 *              corresponding Node.  NOTE: Scope can be null.
 819 *
 820 * MUTEX:       Locks namespace
 821 *
 822 ******************************************************************************/
 823
 824acpi_status
 825acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
 826                 char *pathname,
 827                 u32 flags, struct acpi_namespace_node **return_node)
 828{
 829        union acpi_generic_state scope_info;
 830        acpi_status status;
 831        char *internal_path;
 832
 833        ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname);
 834
 835        if (!pathname) {
 836                *return_node = prefix_node;
 837                if (!prefix_node) {
 838                        *return_node = acpi_gbl_root_node;
 839                }
 840                return_ACPI_STATUS(AE_OK);
 841        }
 842
 843        /* Convert path to internal representation */
 844
 845        status = acpi_ns_internalize_name(pathname, &internal_path);
 846        if (ACPI_FAILURE(status)) {
 847                return_ACPI_STATUS(status);
 848        }
 849
 850        /* Must lock namespace during lookup */
 851
 852        status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
 853        if (ACPI_FAILURE(status)) {
 854                goto cleanup;
 855        }
 856
 857        /* Setup lookup scope (search starting point) */
 858
 859        scope_info.scope.node = prefix_node;
 860
 861        /* Lookup the name in the namespace */
 862
 863        status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
 864                                ACPI_IMODE_EXECUTE,
 865                                (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
 866                                return_node);
 867        if (ACPI_FAILURE(status)) {
 868                ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s, %s\n",
 869                                  pathname, acpi_format_exception(status)));
 870        }
 871
 872        (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 873
 874      cleanup:
 875        ACPI_FREE(internal_path);
 876        return_ACPI_STATUS(status);
 877}
 878
 879/*******************************************************************************
 880 *
 881 * FUNCTION:    acpi_ns_get_parent_node
 882 *
 883 * PARAMETERS:  Node       - Current table entry
 884 *
 885 * RETURN:      Parent entry of the given entry
 886 *
 887 * DESCRIPTION: Obtain the parent entry for a given entry in the namespace.
 888 *
 889 ******************************************************************************/
 890
 891struct acpi_namespace_node *acpi_ns_get_parent_node(struct acpi_namespace_node
 892                                                    *node)
 893{
 894        ACPI_FUNCTION_ENTRY();
 895
 896        if (!node) {
 897                return (NULL);
 898        }
 899
 900        /*
 901         * Walk to the end of this peer list. The last entry is marked with a flag
 902         * and the peer pointer is really a pointer back to the parent. This saves
 903         * putting a parent back pointer in each and every named object!
 904         */
 905        while (!(node->flags & ANOBJ_END_OF_PEER_LIST)) {
 906                node = node->peer;
 907        }
 908
 909        return (node->peer);
 910}
 911
 912/*******************************************************************************
 913 *
 914 * FUNCTION:    acpi_ns_get_next_valid_node
 915 *
 916 * PARAMETERS:  Node       - Current table entry
 917 *
 918 * RETURN:      Next valid Node in the linked node list. NULL if no more valid
 919 *              nodes.
 920 *
 921 * DESCRIPTION: Find the next valid node within a name table.
 922 *              Useful for implementing NULL-end-of-list loops.
 923 *
 924 ******************************************************************************/
 925
 926struct acpi_namespace_node *acpi_ns_get_next_valid_node(struct
 927                                                        acpi_namespace_node
 928                                                        *node)
 929{
 930
 931        /* If we are at the end of this peer list, return NULL */
 932
 933        if (node->flags & ANOBJ_END_OF_PEER_LIST) {
 934                return NULL;
 935        }
 936
 937        /* Otherwise just return the next peer */
 938
 939        return (node->peer);
 940}
 941
 942#ifdef ACPI_OBSOLETE_FUNCTIONS
 943/*******************************************************************************
 944 *
 945 * FUNCTION:    acpi_ns_find_parent_name
 946 *
 947 * PARAMETERS:  *child_node            - Named Obj whose name is to be found
 948 *
 949 * RETURN:      The ACPI name
 950 *
 951 * DESCRIPTION: Search for the given obj in its parent scope and return the
 952 *              name segment, or "????" if the parent name can't be found
 953 *              (which "should not happen").
 954 *
 955 ******************************************************************************/
 956
 957acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node * child_node)
 958{
 959        struct acpi_namespace_node *parent_node;
 960
 961        ACPI_FUNCTION_TRACE(ns_find_parent_name);
 962
 963        if (child_node) {
 964
 965                /* Valid entry.  Get the parent Node */
 966
 967                parent_node = acpi_ns_get_parent_node(child_node);
 968                if (parent_node) {
 969                        ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 970                                          "Parent of %p [%4.4s] is %p [%4.4s]\n",
 971                                          child_node,
 972                                          acpi_ut_get_node_name(child_node),
 973                                          parent_node,
 974                                          acpi_ut_get_node_name(parent_node)));
 975
 976                        if (parent_node->name.integer) {
 977                                return_VALUE((acpi_name) parent_node->name.
 978                                             integer);
 979                        }
 980                }
 981
 982                ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
 983                                  "Unable to find parent of %p (%4.4s)\n",
 984                                  child_node,
 985                                  acpi_ut_get_node_name(child_node)));
 986        }
 987
 988        return_VALUE(ACPI_UNKNOWN_NAME);
 989}
 990#endif
 991