Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
0002 /******************************************************************************
0003  *
0004  * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing
0005  *                        parents and siblings and Scope manipulation
0006  *
0007  * Copyright (C) 2000 - 2022, Intel Corp.
0008  *
0009  *****************************************************************************/
0010 
0011 #include <acpi/acpi.h>
0012 #include "accommon.h"
0013 #include "acnamesp.h"
0014 #include "amlcode.h"
0015 
0016 #define _COMPONENT          ACPI_NAMESPACE
0017 ACPI_MODULE_NAME("nsutils")
0018 
0019 /* Local prototypes */
0020 #ifdef ACPI_OBSOLETE_FUNCTIONS
0021 acpi_name acpi_ns_find_parent_name(struct acpi_namespace_node *node_to_search);
0022 #endif
0023 
0024 /*******************************************************************************
0025  *
0026  * FUNCTION:    acpi_ns_print_node_pathname
0027  *
0028  * PARAMETERS:  node            - Object
0029  *              message         - Prefix message
0030  *
0031  * DESCRIPTION: Print an object's full namespace pathname
0032  *              Manages allocation/freeing of a pathname buffer
0033  *
0034  ******************************************************************************/
0035 
0036 void
0037 acpi_ns_print_node_pathname(struct acpi_namespace_node *node,
0038                 const char *message)
0039 {
0040     struct acpi_buffer buffer;
0041     acpi_status status;
0042 
0043     if (!node) {
0044         acpi_os_printf("[NULL NAME]");
0045         return;
0046     }
0047 
0048     /* Convert handle to full pathname and print it (with supplied message) */
0049 
0050     buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;
0051 
0052     status = acpi_ns_handle_to_pathname(node, &buffer, TRUE);
0053     if (ACPI_SUCCESS(status)) {
0054         if (message) {
0055             acpi_os_printf("%s ", message);
0056         }
0057 
0058         acpi_os_printf("%s", (char *)buffer.pointer);
0059         ACPI_FREE(buffer.pointer);
0060     }
0061 }
0062 
0063 /*******************************************************************************
0064  *
0065  * FUNCTION:    acpi_ns_get_type
0066  *
0067  * PARAMETERS:  node        - Parent Node to be examined
0068  *
0069  * RETURN:      Type field from Node whose handle is passed
0070  *
0071  * DESCRIPTION: Return the type of a Namespace node
0072  *
0073  ******************************************************************************/
0074 
0075 acpi_object_type acpi_ns_get_type(struct acpi_namespace_node * node)
0076 {
0077     ACPI_FUNCTION_TRACE(ns_get_type);
0078 
0079     if (!node) {
0080         ACPI_WARNING((AE_INFO, "Null Node parameter"));
0081         return_UINT8(ACPI_TYPE_ANY);
0082     }
0083 
0084     return_UINT8(node->type);
0085 }
0086 
0087 /*******************************************************************************
0088  *
0089  * FUNCTION:    acpi_ns_local
0090  *
0091  * PARAMETERS:  type        - A namespace object type
0092  *
0093  * RETURN:      LOCAL if names must be found locally in objects of the
0094  *              passed type, 0 if enclosing scopes should be searched
0095  *
0096  * DESCRIPTION: Returns scope rule for the given object type.
0097  *
0098  ******************************************************************************/
0099 
0100 u32 acpi_ns_local(acpi_object_type type)
0101 {
0102     ACPI_FUNCTION_TRACE(ns_local);
0103 
0104     if (!acpi_ut_valid_object_type(type)) {
0105 
0106         /* Type code out of range  */
0107 
0108         ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
0109         return_UINT32(ACPI_NS_NORMAL);
0110     }
0111 
0112     return_UINT32(acpi_gbl_ns_properties[type] & ACPI_NS_LOCAL);
0113 }
0114 
0115 /*******************************************************************************
0116  *
0117  * FUNCTION:    acpi_ns_get_internal_name_length
0118  *
0119  * PARAMETERS:  info            - Info struct initialized with the
0120  *                                external name pointer.
0121  *
0122  * RETURN:      None
0123  *
0124  * DESCRIPTION: Calculate the length of the internal (AML) namestring
0125  *              corresponding to the external (ASL) namestring.
0126  *
0127  ******************************************************************************/
0128 
0129 void acpi_ns_get_internal_name_length(struct acpi_namestring_info *info)
0130 {
0131     const char *next_external_char;
0132     u32 i;
0133 
0134     ACPI_FUNCTION_ENTRY();
0135 
0136     next_external_char = info->external_name;
0137     info->num_carats = 0;
0138     info->num_segments = 0;
0139     info->fully_qualified = FALSE;
0140 
0141     /*
0142      * For the internal name, the required length is 4 bytes per segment,
0143      * plus 1 each for root_prefix, multi_name_prefix_op, segment count,
0144      * trailing null (which is not really needed, but no there's harm in
0145      * putting it there)
0146      *
0147      * strlen() + 1 covers the first name_seg, which has no path separator
0148      */
0149     if (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
0150         info->fully_qualified = TRUE;
0151         next_external_char++;
0152 
0153         /* Skip redundant root_prefix, like \\_SB.PCI0.SBRG.EC0 */
0154 
0155         while (ACPI_IS_ROOT_PREFIX(*next_external_char)) {
0156             next_external_char++;
0157         }
0158     } else {
0159         /* Handle Carat prefixes */
0160 
0161         while (ACPI_IS_PARENT_PREFIX(*next_external_char)) {
0162             info->num_carats++;
0163             next_external_char++;
0164         }
0165     }
0166 
0167     /*
0168      * Determine the number of ACPI name "segments" by counting the number of
0169      * path separators within the string. Start with one segment since the
0170      * segment count is [(# separators) + 1], and zero separators is ok.
0171      */
0172     if (*next_external_char) {
0173         info->num_segments = 1;
0174         for (i = 0; next_external_char[i]; i++) {
0175             if (ACPI_IS_PATH_SEPARATOR(next_external_char[i])) {
0176                 info->num_segments++;
0177             }
0178         }
0179     }
0180 
0181     info->length = (ACPI_NAMESEG_SIZE * info->num_segments) +
0182         4 + info->num_carats;
0183 
0184     info->next_external_char = next_external_char;
0185 }
0186 
0187 /*******************************************************************************
0188  *
0189  * FUNCTION:    acpi_ns_build_internal_name
0190  *
0191  * PARAMETERS:  info            - Info struct fully initialized
0192  *
0193  * RETURN:      Status
0194  *
0195  * DESCRIPTION: Construct the internal (AML) namestring
0196  *              corresponding to the external (ASL) namestring.
0197  *
0198  ******************************************************************************/
0199 
0200 acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
0201 {
0202     u32 num_segments = info->num_segments;
0203     char *internal_name = info->internal_name;
0204     const char *external_name = info->next_external_char;
0205     char *result = NULL;
0206     u32 i;
0207 
0208     ACPI_FUNCTION_TRACE(ns_build_internal_name);
0209 
0210     /* Setup the correct prefixes, counts, and pointers */
0211 
0212     if (info->fully_qualified) {
0213         internal_name[0] = AML_ROOT_PREFIX;
0214 
0215         if (num_segments <= 1) {
0216             result = &internal_name[1];
0217         } else if (num_segments == 2) {
0218             internal_name[1] = AML_DUAL_NAME_PREFIX;
0219             result = &internal_name[2];
0220         } else {
0221             internal_name[1] = AML_MULTI_NAME_PREFIX;
0222             internal_name[2] = (char)num_segments;
0223             result = &internal_name[3];
0224         }
0225     } else {
0226         /*
0227          * Not fully qualified.
0228          * Handle Carats first, then append the name segments
0229          */
0230         i = 0;
0231         if (info->num_carats) {
0232             for (i = 0; i < info->num_carats; i++) {
0233                 internal_name[i] = AML_PARENT_PREFIX;
0234             }
0235         }
0236 
0237         if (num_segments <= 1) {
0238             result = &internal_name[i];
0239         } else if (num_segments == 2) {
0240             internal_name[i] = AML_DUAL_NAME_PREFIX;
0241             result = &internal_name[(acpi_size)i + 1];
0242         } else {
0243             internal_name[i] = AML_MULTI_NAME_PREFIX;
0244             internal_name[(acpi_size)i + 1] = (char)num_segments;
0245             result = &internal_name[(acpi_size)i + 2];
0246         }
0247     }
0248 
0249     /* Build the name (minus path separators) */
0250 
0251     for (; num_segments; num_segments--) {
0252         for (i = 0; i < ACPI_NAMESEG_SIZE; i++) {
0253             if (ACPI_IS_PATH_SEPARATOR(*external_name) ||
0254                 (*external_name == 0)) {
0255 
0256                 /* Pad the segment with underscore(s) if segment is short */
0257 
0258                 result[i] = '_';
0259             } else {
0260                 /* Convert the character to uppercase and save it */
0261 
0262                 result[i] = (char)toupper((int)*external_name);
0263                 external_name++;
0264             }
0265         }
0266 
0267         /* Now we must have a path separator, or the pathname is bad */
0268 
0269         if (!ACPI_IS_PATH_SEPARATOR(*external_name) &&
0270             (*external_name != 0)) {
0271             return_ACPI_STATUS(AE_BAD_PATHNAME);
0272         }
0273 
0274         /* Move on the next segment */
0275 
0276         external_name++;
0277         result += ACPI_NAMESEG_SIZE;
0278     }
0279 
0280     /* Terminate the string */
0281 
0282     *result = 0;
0283 
0284     if (info->fully_qualified) {
0285         ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
0286                   "Returning [%p] (abs) \"\\%s\"\n",
0287                   internal_name, internal_name));
0288     } else {
0289         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Returning [%p] (rel) \"%s\"\n",
0290                   internal_name, internal_name));
0291     }
0292 
0293     return_ACPI_STATUS(AE_OK);
0294 }
0295 
0296 /*******************************************************************************
0297  *
0298  * FUNCTION:    acpi_ns_internalize_name
0299  *
0300  * PARAMETERS:  *external_name          - External representation of name
0301  *              **Converted name        - Where to return the resulting
0302  *                                        internal represention of the name
0303  *
0304  * RETURN:      Status
0305  *
0306  * DESCRIPTION: Convert an external representation (e.g. "\_PR_.CPU0")
0307  *              to internal form (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
0308  *
0309  *******************************************************************************/
0310 
0311 acpi_status
0312 acpi_ns_internalize_name(const char *external_name, char **converted_name)
0313 {
0314     char *internal_name;
0315     struct acpi_namestring_info info;
0316     acpi_status status;
0317 
0318     ACPI_FUNCTION_TRACE(ns_internalize_name);
0319 
0320     if ((!external_name) || (*external_name == 0) || (!converted_name)) {
0321         return_ACPI_STATUS(AE_BAD_PARAMETER);
0322     }
0323 
0324     /* Get the length of the new internal name */
0325 
0326     info.external_name = external_name;
0327     acpi_ns_get_internal_name_length(&info);
0328 
0329     /* We need a segment to store the internal  name */
0330 
0331     internal_name = ACPI_ALLOCATE_ZEROED(info.length);
0332     if (!internal_name) {
0333         return_ACPI_STATUS(AE_NO_MEMORY);
0334     }
0335 
0336     /* Build the name */
0337 
0338     info.internal_name = internal_name;
0339     status = acpi_ns_build_internal_name(&info);
0340     if (ACPI_FAILURE(status)) {
0341         ACPI_FREE(internal_name);
0342         return_ACPI_STATUS(status);
0343     }
0344 
0345     *converted_name = internal_name;
0346     return_ACPI_STATUS(AE_OK);
0347 }
0348 
0349 /*******************************************************************************
0350  *
0351  * FUNCTION:    acpi_ns_externalize_name
0352  *
0353  * PARAMETERS:  internal_name_length - Length of the internal name below
0354  *              internal_name       - Internal representation of name
0355  *              converted_name_length - Where the length is returned
0356  *              converted_name      - Where the resulting external name
0357  *                                    is returned
0358  *
0359  * RETURN:      Status
0360  *
0361  * DESCRIPTION: Convert internal name (e.g. 5c 2f 02 5f 50 52 5f 43 50 55 30)
0362  *              to its external (printable) form (e.g. "\_PR_.CPU0")
0363  *
0364  ******************************************************************************/
0365 
0366 acpi_status
0367 acpi_ns_externalize_name(u32 internal_name_length,
0368              const char *internal_name,
0369              u32 * converted_name_length, char **converted_name)
0370 {
0371     u32 names_index = 0;
0372     u32 num_segments = 0;
0373     u32 required_length;
0374     u32 prefix_length = 0;
0375     u32 i = 0;
0376     u32 j = 0;
0377 
0378     ACPI_FUNCTION_TRACE(ns_externalize_name);
0379 
0380     if (!internal_name_length || !internal_name || !converted_name) {
0381         return_ACPI_STATUS(AE_BAD_PARAMETER);
0382     }
0383 
0384     /* Check for a prefix (one '\' | one or more '^') */
0385 
0386     switch (internal_name[0]) {
0387     case AML_ROOT_PREFIX:
0388 
0389         prefix_length = 1;
0390         break;
0391 
0392     case AML_PARENT_PREFIX:
0393 
0394         for (i = 0; i < internal_name_length; i++) {
0395             if (ACPI_IS_PARENT_PREFIX(internal_name[i])) {
0396                 prefix_length = i + 1;
0397             } else {
0398                 break;
0399             }
0400         }
0401 
0402         if (i == internal_name_length) {
0403             prefix_length = i;
0404         }
0405 
0406         break;
0407 
0408     default:
0409 
0410         break;
0411     }
0412 
0413     /*
0414      * Check for object names. Note that there could be 0-255 of these
0415      * 4-byte elements.
0416      */
0417     if (prefix_length < internal_name_length) {
0418         switch (internal_name[prefix_length]) {
0419         case AML_MULTI_NAME_PREFIX:
0420 
0421             /* <count> 4-byte names */
0422 
0423             names_index = prefix_length + 2;
0424             num_segments = (u8)
0425                 internal_name[(acpi_size)prefix_length + 1];
0426             break;
0427 
0428         case AML_DUAL_NAME_PREFIX:
0429 
0430             /* Two 4-byte names */
0431 
0432             names_index = prefix_length + 1;
0433             num_segments = 2;
0434             break;
0435 
0436         case 0:
0437 
0438             /* null_name */
0439 
0440             names_index = 0;
0441             num_segments = 0;
0442             break;
0443 
0444         default:
0445 
0446             /* one 4-byte name */
0447 
0448             names_index = prefix_length;
0449             num_segments = 1;
0450             break;
0451         }
0452     }
0453 
0454     /*
0455      * Calculate the length of converted_name, which equals the length
0456      * of the prefix, length of all object names, length of any required
0457      * punctuation ('.') between object names, plus the NULL terminator.
0458      */
0459     required_length = prefix_length + (4 * num_segments) +
0460         ((num_segments > 0) ? (num_segments - 1) : 0) + 1;
0461 
0462     /*
0463      * Check to see if we're still in bounds. If not, there's a problem
0464      * with internal_name (invalid format).
0465      */
0466     if (required_length > internal_name_length) {
0467         ACPI_ERROR((AE_INFO, "Invalid internal name"));
0468         return_ACPI_STATUS(AE_BAD_PATHNAME);
0469     }
0470 
0471     /* Build the converted_name */
0472 
0473     *converted_name = ACPI_ALLOCATE_ZEROED(required_length);
0474     if (!(*converted_name)) {
0475         return_ACPI_STATUS(AE_NO_MEMORY);
0476     }
0477 
0478     j = 0;
0479 
0480     for (i = 0; i < prefix_length; i++) {
0481         (*converted_name)[j++] = internal_name[i];
0482     }
0483 
0484     if (num_segments > 0) {
0485         for (i = 0; i < num_segments; i++) {
0486             if (i > 0) {
0487                 (*converted_name)[j++] = '.';
0488             }
0489 
0490             /* Copy and validate the 4-char name segment */
0491 
0492             ACPI_COPY_NAMESEG(&(*converted_name)[j],
0493                       &internal_name[names_index]);
0494             acpi_ut_repair_name(&(*converted_name)[j]);
0495 
0496             j += ACPI_NAMESEG_SIZE;
0497             names_index += ACPI_NAMESEG_SIZE;
0498         }
0499     }
0500 
0501     if (converted_name_length) {
0502         *converted_name_length = (u32) required_length;
0503     }
0504 
0505     return_ACPI_STATUS(AE_OK);
0506 }
0507 
0508 /*******************************************************************************
0509  *
0510  * FUNCTION:    acpi_ns_validate_handle
0511  *
0512  * PARAMETERS:  handle          - Handle to be validated and typecast to a
0513  *                                namespace node.
0514  *
0515  * RETURN:      A pointer to a namespace node
0516  *
0517  * DESCRIPTION: Convert a namespace handle to a namespace node. Handles special
0518  *              cases for the root node.
0519  *
0520  * NOTE: Real integer handles would allow for more verification
0521  *       and keep all pointers within this subsystem - however this introduces
0522  *       more overhead and has not been necessary to this point. Drivers
0523  *       holding handles are typically notified before a node becomes invalid
0524  *       due to a table unload.
0525  *
0526  ******************************************************************************/
0527 
0528 struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
0529 {
0530 
0531     ACPI_FUNCTION_ENTRY();
0532 
0533     /* Parameter validation */
0534 
0535     if ((!handle) || (handle == ACPI_ROOT_OBJECT)) {
0536         return (acpi_gbl_root_node);
0537     }
0538 
0539     /* We can at least attempt to verify the handle */
0540 
0541     if (ACPI_GET_DESCRIPTOR_TYPE(handle) != ACPI_DESC_TYPE_NAMED) {
0542         return (NULL);
0543     }
0544 
0545     return (ACPI_CAST_PTR(struct acpi_namespace_node, handle));
0546 }
0547 
0548 /*******************************************************************************
0549  *
0550  * FUNCTION:    acpi_ns_terminate
0551  *
0552  * PARAMETERS:  none
0553  *
0554  * RETURN:      none
0555  *
0556  * DESCRIPTION: free memory allocated for namespace and ACPI table storage.
0557  *
0558  ******************************************************************************/
0559 
0560 void acpi_ns_terminate(void)
0561 {
0562     acpi_status status;
0563 
0564     ACPI_FUNCTION_TRACE(ns_terminate);
0565 
0566     /*
0567      * Free the entire namespace -- all nodes and all objects
0568      * attached to the nodes
0569      */
0570     acpi_ns_delete_namespace_subtree(acpi_gbl_root_node);
0571 
0572     /* Delete any objects attached to the root node */
0573 
0574     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0575     if (ACPI_FAILURE(status)) {
0576         return_VOID;
0577     }
0578 
0579     acpi_ns_delete_node(acpi_gbl_root_node);
0580     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0581 
0582     ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Namespace freed\n"));
0583     return_VOID;
0584 }
0585 
0586 /*******************************************************************************
0587  *
0588  * FUNCTION:    acpi_ns_opens_scope
0589  *
0590  * PARAMETERS:  type        - A valid namespace type
0591  *
0592  * RETURN:      NEWSCOPE if the passed type "opens a name scope" according
0593  *              to the ACPI specification, else 0
0594  *
0595  ******************************************************************************/
0596 
0597 u32 acpi_ns_opens_scope(acpi_object_type type)
0598 {
0599     ACPI_FUNCTION_ENTRY();
0600 
0601     if (type > ACPI_TYPE_LOCAL_MAX) {
0602 
0603         /* type code out of range  */
0604 
0605         ACPI_WARNING((AE_INFO, "Invalid Object Type 0x%X", type));
0606         return (ACPI_NS_NORMAL);
0607     }
0608 
0609     return (((u32)acpi_gbl_ns_properties[type]) & ACPI_NS_NEWSCOPE);
0610 }
0611 
0612 /*******************************************************************************
0613  *
0614  * FUNCTION:    acpi_ns_get_node_unlocked
0615  *
0616  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
0617  *                            \ (backslash) and ^ (carat) prefixes, and the
0618  *                            . (period) to separate segments are supported.
0619  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
0620  *                            root of the name space. If Name is fully
0621  *                            qualified (first s8 is '\'), the passed value
0622  *                            of Scope will not be accessed.
0623  *              flags       - Used to indicate whether to perform upsearch or
0624  *                            not.
0625  *              return_node - Where the Node is returned
0626  *
0627  * DESCRIPTION: Look up a name relative to a given scope and return the
0628  *              corresponding Node. NOTE: Scope can be null.
0629  *
0630  * MUTEX:       Doesn't locks namespace
0631  *
0632  ******************************************************************************/
0633 
0634 acpi_status
0635 acpi_ns_get_node_unlocked(struct acpi_namespace_node *prefix_node,
0636               const char *pathname,
0637               u32 flags, struct acpi_namespace_node **return_node)
0638 {
0639     union acpi_generic_state scope_info;
0640     acpi_status status;
0641     char *internal_path;
0642 
0643     ACPI_FUNCTION_TRACE_PTR(ns_get_node_unlocked,
0644                 ACPI_CAST_PTR(char, pathname));
0645 
0646     /* Simplest case is a null pathname */
0647 
0648     if (!pathname) {
0649         *return_node = prefix_node;
0650         if (!prefix_node) {
0651             *return_node = acpi_gbl_root_node;
0652         }
0653 
0654         return_ACPI_STATUS(AE_OK);
0655     }
0656 
0657     /* Quick check for a reference to the root */
0658 
0659     if (ACPI_IS_ROOT_PREFIX(pathname[0]) && (!pathname[1])) {
0660         *return_node = acpi_gbl_root_node;
0661         return_ACPI_STATUS(AE_OK);
0662     }
0663 
0664     /* Convert path to internal representation */
0665 
0666     status = acpi_ns_internalize_name(pathname, &internal_path);
0667     if (ACPI_FAILURE(status)) {
0668         return_ACPI_STATUS(status);
0669     }
0670 
0671     /* Setup lookup scope (search starting point) */
0672 
0673     scope_info.scope.node = prefix_node;
0674 
0675     /* Lookup the name in the namespace */
0676 
0677     status = acpi_ns_lookup(&scope_info, internal_path, ACPI_TYPE_ANY,
0678                 ACPI_IMODE_EXECUTE,
0679                 (flags | ACPI_NS_DONT_OPEN_SCOPE), NULL,
0680                 return_node);
0681     if (ACPI_FAILURE(status)) {
0682         ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s, %s\n",
0683                   pathname, acpi_format_exception(status)));
0684     }
0685 
0686     ACPI_FREE(internal_path);
0687     return_ACPI_STATUS(status);
0688 }
0689 
0690 /*******************************************************************************
0691  *
0692  * FUNCTION:    acpi_ns_get_node
0693  *
0694  * PARAMETERS:  *pathname   - Name to be found, in external (ASL) format. The
0695  *                            \ (backslash) and ^ (carat) prefixes, and the
0696  *                            . (period) to separate segments are supported.
0697  *              prefix_node  - Root of subtree to be searched, or NS_ALL for the
0698  *                            root of the name space. If Name is fully
0699  *                            qualified (first s8 is '\'), the passed value
0700  *                            of Scope will not be accessed.
0701  *              flags       - Used to indicate whether to perform upsearch or
0702  *                            not.
0703  *              return_node - Where the Node is returned
0704  *
0705  * DESCRIPTION: Look up a name relative to a given scope and return the
0706  *              corresponding Node. NOTE: Scope can be null.
0707  *
0708  * MUTEX:       Locks namespace
0709  *
0710  ******************************************************************************/
0711 
0712 acpi_status
0713 acpi_ns_get_node(struct acpi_namespace_node *prefix_node,
0714          const char *pathname,
0715          u32 flags, struct acpi_namespace_node **return_node)
0716 {
0717     acpi_status status;
0718 
0719     ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname));
0720 
0721     status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
0722     if (ACPI_FAILURE(status)) {
0723         return_ACPI_STATUS(status);
0724     }
0725 
0726     status = acpi_ns_get_node_unlocked(prefix_node, pathname,
0727                        flags, return_node);
0728 
0729     (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
0730     return_ACPI_STATUS(status);
0731 }