LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - nsxfname.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 122 192 63.5 %
Date: 2022-04-01 14:35:51 Functions: 4 5 80.0 %
Branches: 57 98 58.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
       5                 :            :  *                         ACPI Namespace oriented interfaces
       6                 :            :  *
       7                 :            :  * Copyright (C) 2000 - 2020, Intel Corp.
       8                 :            :  *
       9                 :            :  *****************************************************************************/
      10                 :            : 
      11                 :            : #define EXPORT_ACPI_INTERFACES
      12                 :            : 
      13                 :            : #include <acpi/acpi.h>
      14                 :            : #include "accommon.h"
      15                 :            : #include "acnamesp.h"
      16                 :            : #include "acparser.h"
      17                 :            : #include "amlcode.h"
      18                 :            : 
      19                 :            : #define _COMPONENT          ACPI_NAMESPACE
      20                 :            : ACPI_MODULE_NAME("nsxfname")
      21                 :            : 
      22                 :            : /* Local prototypes */
      23                 :            : static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
      24                 :            :                                     struct acpi_pnp_device_id *source,
      25                 :            :                                     char *string_area);
      26                 :            : 
      27                 :            : /******************************************************************************
      28                 :            :  *
      29                 :            :  * FUNCTION:    acpi_get_handle
      30                 :            :  *
      31                 :            :  * PARAMETERS:  parent          - Object to search under (search scope).
      32                 :            :  *              pathname        - Pointer to an asciiz string containing the
      33                 :            :  *                                name
      34                 :            :  *              ret_handle      - Where the return handle is returned
      35                 :            :  *
      36                 :            :  * RETURN:      Status
      37                 :            :  *
      38                 :            :  * DESCRIPTION: This routine will search for a caller specified name in the
      39                 :            :  *              name space. The caller can restrict the search region by
      40                 :            :  *              specifying a non NULL parent. The parent value is itself a
      41                 :            :  *              namespace handle.
      42                 :            :  *
      43                 :            :  ******************************************************************************/
      44                 :            : 
      45                 :            : acpi_status
      46                 :      45570 : acpi_get_handle(acpi_handle parent,
      47                 :            :                 acpi_string pathname, acpi_handle *ret_handle)
      48                 :            : {
      49                 :      45570 :         acpi_status status;
      50                 :      45570 :         struct acpi_namespace_node *node = NULL;
      51                 :      45570 :         struct acpi_namespace_node *prefix_node = NULL;
      52                 :            : 
      53                 :      45570 :         ACPI_FUNCTION_ENTRY();
      54                 :            : 
      55                 :            :         /* Parameter Validation */
      56                 :            : 
      57         [ +  - ]:      45570 :         if (!ret_handle || !pathname) {
      58                 :            :                 return (AE_BAD_PARAMETER);
      59                 :            :         }
      60                 :            : 
      61                 :            :         /* Convert a parent handle to a prefix node */
      62                 :            : 
      63         [ +  + ]:      45570 :         if (parent) {
      64                 :      43764 :                 prefix_node = acpi_ns_validate_handle(parent);
      65         [ +  - ]:      43764 :                 if (!prefix_node) {
      66                 :            :                         return (AE_BAD_PARAMETER);
      67                 :            :                 }
      68                 :            :         }
      69                 :            : 
      70                 :            :         /*
      71                 :            :          * Valid cases are:
      72                 :            :          * 1) Fully qualified pathname
      73                 :            :          * 2) Parent + Relative pathname
      74                 :            :          *
      75                 :            :          * Error for <null Parent + relative path>
      76                 :            :          */
      77         [ +  + ]:      45570 :         if (ACPI_IS_ROOT_PREFIX(pathname[0])) {
      78                 :            : 
      79                 :            :                 /* Pathname is fully qualified (starts with '\') */
      80                 :            : 
      81                 :            :                 /* Special case for root-only, since we can't search for it */
      82                 :            : 
      83         [ -  + ]:       1575 :                 if (!strcmp(pathname, ACPI_NS_ROOT_PATH)) {
      84                 :          0 :                         *ret_handle =
      85                 :            :                             ACPI_CAST_PTR(acpi_handle, acpi_gbl_root_node);
      86                 :          0 :                         return (AE_OK);
      87                 :            :                 }
      88         [ +  + ]:      43995 :         } else if (!prefix_node) {
      89                 :            : 
      90                 :            :                 /* Relative path with null prefix is disallowed */
      91                 :            : 
      92                 :            :                 return (AE_BAD_PARAMETER);
      93                 :            :         }
      94                 :            : 
      95                 :            :         /* Find the Node and convert to a handle */
      96                 :            : 
      97                 :      45318 :         status =
      98                 :      45318 :             acpi_ns_get_node(prefix_node, pathname, ACPI_NS_NO_UPSEARCH, &node);
      99         [ +  + ]:      45318 :         if (ACPI_SUCCESS(status)) {
     100                 :       8400 :                 *ret_handle = ACPI_CAST_PTR(acpi_handle, node);
     101                 :            :         }
     102                 :            : 
     103                 :            :         return (status);
     104                 :            : }
     105                 :            : 
     106                 :            : ACPI_EXPORT_SYMBOL(acpi_get_handle)
     107                 :            : 
     108                 :            : /******************************************************************************
     109                 :            :  *
     110                 :            :  * FUNCTION:    acpi_get_name
     111                 :            :  *
     112                 :            :  * PARAMETERS:  handle          - Handle to be converted to a pathname
     113                 :            :  *              name_type       - Full pathname or single segment
     114                 :            :  *              buffer          - Buffer for returned path
     115                 :            :  *
     116                 :            :  * RETURN:      Pointer to a string containing the fully qualified Name.
     117                 :            :  *
     118                 :            :  * DESCRIPTION: This routine returns the fully qualified name associated with
     119                 :            :  *              the Handle parameter. This and the acpi_pathname_to_handle are
     120                 :            :  *              complementary functions.
     121                 :            :  *
     122                 :            :  ******************************************************************************/
     123                 :            : acpi_status
     124                 :       2394 : acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer *buffer)
     125                 :            : {
     126                 :       2394 :         acpi_status status;
     127                 :            : 
     128                 :            :         /* Parameter validation */
     129                 :            : 
     130         [ +  - ]:       2394 :         if (name_type > ACPI_NAME_TYPE_MAX) {
     131                 :            :                 return (AE_BAD_PARAMETER);
     132                 :            :         }
     133                 :            : 
     134                 :       2394 :         status = acpi_ut_validate_buffer(buffer);
     135         [ +  - ]:       2394 :         if (ACPI_FAILURE(status)) {
     136                 :            :                 return (status);
     137                 :            :         }
     138                 :            : 
     139                 :            :         /*
     140                 :            :          * Wants the single segment ACPI name.
     141                 :            :          * Validate handle and convert to a namespace Node
     142                 :            :          */
     143                 :       2394 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     144         [ +  - ]:       2394 :         if (ACPI_FAILURE(status)) {
     145                 :            :                 return (status);
     146                 :            :         }
     147                 :            : 
     148                 :       2394 :         if (name_type == ACPI_FULL_PATHNAME ||
     149         [ +  + ]:       2394 :             name_type == ACPI_FULL_PATHNAME_NO_TRAILING) {
     150                 :            : 
     151                 :            :                 /* Get the full pathname (From the namespace root) */
     152                 :            : 
     153                 :       1218 :                 status = acpi_ns_handle_to_pathname(handle, buffer,
     154                 :            :                                                     name_type ==
     155                 :            :                                                     ACPI_FULL_PATHNAME ? FALSE :
     156                 :            :                                                     TRUE);
     157                 :            :         } else {
     158                 :            :                 /* Get the single name */
     159                 :            : 
     160                 :       1176 :                 status = acpi_ns_handle_to_name(handle, buffer);
     161                 :            :         }
     162                 :            : 
     163                 :       2394 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     164                 :       2394 :         return (status);
     165                 :            : }
     166                 :            : 
     167                 :            : ACPI_EXPORT_SYMBOL(acpi_get_name)
     168                 :            : 
     169                 :            : /******************************************************************************
     170                 :            :  *
     171                 :            :  * FUNCTION:    acpi_ns_copy_device_id
     172                 :            :  *
     173                 :            :  * PARAMETERS:  dest                - Pointer to the destination PNP_DEVICE_ID
     174                 :            :  *              source              - Pointer to the source PNP_DEVICE_ID
     175                 :            :  *              string_area         - Pointer to where to copy the dest string
     176                 :            :  *
     177                 :            :  * RETURN:      Pointer to the next string area
     178                 :            :  *
     179                 :            :  * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data.
     180                 :            :  *
     181                 :            :  ******************************************************************************/
     182                 :       1344 : static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
     183                 :            :                                     struct acpi_pnp_device_id *source,
     184                 :            :                                     char *string_area)
     185                 :            : {
     186                 :            :         /* Create the destination PNP_DEVICE_ID */
     187                 :            : 
     188                 :       1344 :         dest->string = string_area;
     189                 :       1344 :         dest->length = source->length;
     190                 :            : 
     191                 :            :         /* Copy actual string and return a pointer to the next string area */
     192                 :            : 
     193                 :       1344 :         memcpy(string_area, source->string, source->length);
     194                 :       1344 :         return (string_area + source->length);
     195                 :            : }
     196                 :            : 
     197                 :            : /******************************************************************************
     198                 :            :  *
     199                 :            :  * FUNCTION:    acpi_get_object_info
     200                 :            :  *
     201                 :            :  * PARAMETERS:  handle              - Object Handle
     202                 :            :  *              return_buffer       - Where the info is returned
     203                 :            :  *
     204                 :            :  * RETURN:      Status
     205                 :            :  *
     206                 :            :  * DESCRIPTION: Returns information about an object as gleaned from the
     207                 :            :  *              namespace node and possibly by running several standard
     208                 :            :  *              control methods (Such as in the case of a device.)
     209                 :            :  *
     210                 :            :  * For Device and Processor objects, run the Device _HID, _UID, _CID,
     211                 :            :  * _CLS, _ADR, _sx_w, and _sx_d methods.
     212                 :            :  *
     213                 :            :  * Note: Allocates the return buffer, must be freed by the caller.
     214                 :            :  *
     215                 :            :  * Note: This interface is intended to be used during the initial device
     216                 :            :  * discovery namespace traversal. Therefore, no complex methods can be
     217                 :            :  * executed, especially those that access operation regions. Therefore, do
     218                 :            :  * not add any additional methods that could cause problems in this area.
     219                 :            :  * Because of this reason support for the following methods has been removed:
     220                 :            :  * 1) _SUB method was removed (11/2015)
     221                 :            :  * 2) _STA method was removed (02/2018)
     222                 :            :  *
     223                 :            :  ******************************************************************************/
     224                 :            : 
     225                 :            : acpi_status
     226                 :       2310 : acpi_get_object_info(acpi_handle handle,
     227                 :            :                      struct acpi_device_info **return_buffer)
     228                 :            : {
     229                 :       2310 :         struct acpi_namespace_node *node;
     230                 :       2310 :         struct acpi_device_info *info;
     231                 :       2310 :         struct acpi_pnp_device_id_list *cid_list = NULL;
     232                 :       2310 :         struct acpi_pnp_device_id *hid = NULL;
     233                 :       2310 :         struct acpi_pnp_device_id *uid = NULL;
     234                 :       2310 :         struct acpi_pnp_device_id *cls = NULL;
     235                 :       2310 :         char *next_id_string;
     236                 :       2310 :         acpi_object_type type;
     237                 :       2310 :         acpi_name name;
     238                 :       2310 :         u8 param_count = 0;
     239                 :       2310 :         u16 valid = 0;
     240                 :       2310 :         u32 info_size;
     241                 :       2310 :         u32 i;
     242                 :       2310 :         acpi_status status;
     243                 :            : 
     244                 :            :         /* Parameter validation */
     245                 :            : 
     246         [ +  - ]:       2310 :         if (!handle || !return_buffer) {
     247                 :            :                 return (AE_BAD_PARAMETER);
     248                 :            :         }
     249                 :            : 
     250                 :       2310 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     251         [ +  - ]:       2310 :         if (ACPI_FAILURE(status)) {
     252                 :            :                 return (status);
     253                 :            :         }
     254                 :            : 
     255                 :       2310 :         node = acpi_ns_validate_handle(handle);
     256         [ -  + ]:       2310 :         if (!node) {
     257                 :          0 :                 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     258                 :          0 :                 return (AE_BAD_PARAMETER);
     259                 :            :         }
     260                 :            : 
     261                 :            :         /* Get the namespace node data while the namespace is locked */
     262                 :            : 
     263                 :       2310 :         info_size = sizeof(struct acpi_device_info);
     264                 :       2310 :         type = node->type;
     265                 :       2310 :         name = node->name.integer;
     266                 :            : 
     267         [ -  + ]:       2310 :         if (node->type == ACPI_TYPE_METHOD) {
     268                 :          0 :                 param_count = node->object->method.param_count;
     269                 :            :         }
     270                 :            : 
     271                 :       2310 :         status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     272         [ +  - ]:       2310 :         if (ACPI_FAILURE(status)) {
     273                 :            :                 return (status);
     274                 :            :         }
     275                 :            : 
     276         [ +  - ]:       2310 :         if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
     277                 :            :                 /*
     278                 :            :                  * Get extra info for ACPI Device/Processor objects only:
     279                 :            :                  * Run the Device _HID, _UID, _CLS, and _CID methods.
     280                 :            :                  *
     281                 :            :                  * Note: none of these methods are required, so they may or may
     282                 :            :                  * not be present for this device. The Info->Valid bitfield is used
     283                 :            :                  * to indicate which methods were found and run successfully.
     284                 :            :                  */
     285                 :            : 
     286                 :            :                 /* Execute the Device._HID method */
     287                 :            : 
     288                 :       2310 :                 status = acpi_ut_execute_HID(node, &hid);
     289         [ +  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     290                 :        798 :                         info_size += hid->length;
     291                 :        798 :                         valid |= ACPI_VALID_HID;
     292                 :            :                 }
     293                 :            : 
     294                 :            :                 /* Execute the Device._UID method */
     295                 :            : 
     296                 :       2310 :                 status = acpi_ut_execute_UID(node, &uid);
     297         [ +  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     298                 :        504 :                         info_size += uid->length;
     299                 :        504 :                         valid |= ACPI_VALID_UID;
     300                 :            :                 }
     301                 :            : 
     302                 :            :                 /* Execute the Device._CID method */
     303                 :            : 
     304                 :       2310 :                 status = acpi_ut_execute_CID(node, &cid_list);
     305         [ +  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     306                 :            : 
     307                 :            :                         /* Add size of CID strings and CID pointer array */
     308                 :            : 
     309                 :         42 :                         info_size +=
     310                 :         42 :                             (cid_list->list_size -
     311                 :            :                              sizeof(struct acpi_pnp_device_id_list));
     312                 :         42 :                         valid |= ACPI_VALID_CID;
     313                 :            :                 }
     314                 :            : 
     315                 :            :                 /* Execute the Device._CLS method */
     316                 :            : 
     317                 :       2310 :                 status = acpi_ut_execute_CLS(node, &cls);
     318         [ -  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     319                 :          0 :                         info_size += cls->length;
     320                 :          0 :                         valid |= ACPI_VALID_CLS;
     321                 :            :                 }
     322                 :            :         }
     323                 :            : 
     324                 :            :         /*
     325                 :            :          * Now that we have the variable-length data, we can allocate the
     326                 :            :          * return buffer
     327                 :            :          */
     328                 :       2310 :         info = ACPI_ALLOCATE_ZEROED(info_size);
     329         [ -  + ]:       2310 :         if (!info) {
     330                 :          0 :                 status = AE_NO_MEMORY;
     331                 :          0 :                 goto cleanup;
     332                 :            :         }
     333                 :            : 
     334                 :            :         /* Get the fixed-length data */
     335                 :            : 
     336         [ +  - ]:       2310 :         if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
     337                 :            :                 /*
     338                 :            :                  * Get extra info for ACPI Device/Processor objects only:
     339                 :            :                  * Run the _ADR and, sx_w, and _sx_d methods.
     340                 :            :                  *
     341                 :            :                  * Notes: none of these methods are required, so they may or may
     342                 :            :                  * not be present for this device. The Info->Valid bitfield is used
     343                 :            :                  * to indicate which methods were found and run successfully.
     344                 :            :                  */
     345                 :            : 
     346                 :            :                 /* Execute the Device._ADR method */
     347                 :            : 
     348                 :       2310 :                 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node,
     349                 :            :                                                          &info->address);
     350         [ +  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     351                 :       1470 :                         valid |= ACPI_VALID_ADR;
     352                 :            :                 }
     353                 :            : 
     354                 :            :                 /* Execute the Device._sx_w methods */
     355                 :            : 
     356                 :       2310 :                 status = acpi_ut_execute_power_methods(node,
     357                 :            :                                                        acpi_gbl_lowest_dstate_names,
     358                 :            :                                                        ACPI_NUM_sx_w_METHODS,
     359                 :       2310 :                                                        info->lowest_dstates);
     360         [ -  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     361                 :          0 :                         valid |= ACPI_VALID_SXWS;
     362                 :            :                 }
     363                 :            : 
     364                 :            :                 /* Execute the Device._sx_d methods */
     365                 :            : 
     366                 :       2310 :                 status = acpi_ut_execute_power_methods(node,
     367                 :            :                                                        acpi_gbl_highest_dstate_names,
     368                 :            :                                                        ACPI_NUM_sx_d_METHODS,
     369                 :       2310 :                                                        info->highest_dstates);
     370         [ +  + ]:       2310 :                 if (ACPI_SUCCESS(status)) {
     371                 :         42 :                         valid |= ACPI_VALID_SXDS;
     372                 :            :                 }
     373                 :            :         }
     374                 :            : 
     375                 :            :         /*
     376                 :            :          * Create a pointer to the string area of the return buffer.
     377                 :            :          * Point to the end of the base struct acpi_device_info structure.
     378                 :            :          */
     379                 :       2310 :         next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids);
     380         [ +  + ]:       2310 :         if (cid_list) {
     381                 :            : 
     382                 :            :                 /* Point past the CID PNP_DEVICE_ID array */
     383                 :            : 
     384                 :         42 :                 next_id_string +=
     385                 :         42 :                     ((acpi_size)cid_list->count *
     386                 :            :                      sizeof(struct acpi_pnp_device_id));
     387                 :            :         }
     388                 :            : 
     389                 :            :         /*
     390                 :            :          * Copy the HID, UID, and CIDs to the return buffer. The variable-length
     391                 :            :          * strings are copied to the reserved area at the end of the buffer.
     392                 :            :          *
     393                 :            :          * For HID and CID, check if the ID is a PCI Root Bridge.
     394                 :            :          */
     395         [ +  + ]:       2310 :         if (hid) {
     396                 :        798 :                 next_id_string = acpi_ns_copy_device_id(&info->hardware_id,
     397                 :            :                                                         hid, next_id_string);
     398                 :            : 
     399         [ +  + ]:        798 :                 if (acpi_ut_is_pci_root_bridge(hid->string)) {
     400                 :         42 :                         info->flags |= ACPI_PCI_ROOT_BRIDGE;
     401                 :            :                 }
     402                 :            :         }
     403                 :            : 
     404         [ +  + ]:       2310 :         if (uid) {
     405                 :        504 :                 next_id_string = acpi_ns_copy_device_id(&info->unique_id,
     406                 :            :                                                         uid, next_id_string);
     407                 :            :         }
     408                 :            : 
     409         [ +  + ]:       2310 :         if (cid_list) {
     410                 :         42 :                 info->compatible_id_list.count = cid_list->count;
     411                 :         42 :                 info->compatible_id_list.list_size = cid_list->list_size;
     412                 :            : 
     413                 :            :                 /* Copy each CID */
     414                 :            : 
     415         [ +  + ]:         84 :                 for (i = 0; i < cid_list->count; i++) {
     416                 :         42 :                         next_id_string =
     417                 :         42 :                             acpi_ns_copy_device_id(&info->compatible_id_list.
     418                 :            :                                                    ids[i], &cid_list->ids[i],
     419                 :            :                                                    next_id_string);
     420                 :            : 
     421         [ -  + ]:         42 :                         if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) {
     422                 :          0 :                                 info->flags |= ACPI_PCI_ROOT_BRIDGE;
     423                 :            :                         }
     424                 :            :                 }
     425                 :            :         }
     426                 :            : 
     427         [ -  + ]:       2310 :         if (cls) {
     428                 :          0 :                 (void)acpi_ns_copy_device_id(&info->class_code,
     429                 :            :                                              cls, next_id_string);
     430                 :            :         }
     431                 :            : 
     432                 :            :         /* Copy the fixed-length data */
     433                 :            : 
     434                 :       2310 :         info->info_size = info_size;
     435                 :       2310 :         info->type = type;
     436                 :       2310 :         info->name = name;
     437                 :       2310 :         info->param_count = param_count;
     438                 :       2310 :         info->valid = valid;
     439                 :            : 
     440                 :       2310 :         *return_buffer = info;
     441                 :       2310 :         status = AE_OK;
     442                 :            : 
     443                 :       2310 : cleanup:
     444         [ +  + ]:       2310 :         if (hid) {
     445                 :        798 :                 ACPI_FREE(hid);
     446                 :            :         }
     447         [ +  + ]:       2310 :         if (uid) {
     448                 :        504 :                 ACPI_FREE(uid);
     449                 :            :         }
     450         [ +  + ]:       2310 :         if (cid_list) {
     451                 :         42 :                 ACPI_FREE(cid_list);
     452                 :            :         }
     453         [ -  + ]:       2310 :         if (cls) {
     454                 :          0 :                 ACPI_FREE(cls);
     455                 :            :         }
     456                 :            :         return (status);
     457                 :            : }
     458                 :            : 
     459                 :            : ACPI_EXPORT_SYMBOL(acpi_get_object_info)
     460                 :            : 
     461                 :            : /******************************************************************************
     462                 :            :  *
     463                 :            :  * FUNCTION:    acpi_install_method
     464                 :            :  *
     465                 :            :  * PARAMETERS:  buffer         - An ACPI table containing one control method
     466                 :            :  *
     467                 :            :  * RETURN:      Status
     468                 :            :  *
     469                 :            :  * DESCRIPTION: Install a control method into the namespace. If the method
     470                 :            :  *              name already exists in the namespace, it is overwritten. The
     471                 :            :  *              input buffer must contain a valid DSDT or SSDT containing a
     472                 :            :  *              single control method.
     473                 :            :  *
     474                 :            :  ******************************************************************************/
     475                 :          0 : acpi_status acpi_install_method(u8 *buffer)
     476                 :            : {
     477                 :          0 :         struct acpi_table_header *table =
     478                 :            :             ACPI_CAST_PTR(struct acpi_table_header, buffer);
     479                 :          0 :         u8 *aml_buffer;
     480                 :          0 :         u8 *aml_start;
     481                 :          0 :         char *path;
     482                 :          0 :         struct acpi_namespace_node *node;
     483                 :          0 :         union acpi_operand_object *method_obj;
     484                 :          0 :         struct acpi_parse_state parser_state;
     485                 :          0 :         u32 aml_length;
     486                 :          0 :         u16 opcode;
     487                 :          0 :         u8 method_flags;
     488                 :          0 :         acpi_status status;
     489                 :            : 
     490                 :            :         /* Parameter validation */
     491                 :            : 
     492         [ #  # ]:          0 :         if (!buffer) {
     493                 :            :                 return (AE_BAD_PARAMETER);
     494                 :            :         }
     495                 :            : 
     496                 :            :         /* Table must be a DSDT or SSDT */
     497                 :            : 
     498   [ #  #  #  # ]:          0 :         if (!ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) &&
     499                 :            :             !ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT)) {
     500                 :            :                 return (AE_BAD_HEADER);
     501                 :            :         }
     502                 :            : 
     503                 :            :         /* First AML opcode in the table must be a control method */
     504                 :            : 
     505                 :          0 :         parser_state.aml = buffer + sizeof(struct acpi_table_header);
     506                 :          0 :         opcode = acpi_ps_peek_opcode(&parser_state);
     507         [ #  # ]:          0 :         if (opcode != AML_METHOD_OP) {
     508                 :            :                 return (AE_BAD_PARAMETER);
     509                 :            :         }
     510                 :            : 
     511                 :            :         /* Extract method information from the raw AML */
     512                 :            : 
     513                 :          0 :         parser_state.aml += acpi_ps_get_opcode_size(opcode);
     514                 :          0 :         parser_state.pkg_end = acpi_ps_get_next_package_end(&parser_state);
     515                 :          0 :         path = acpi_ps_get_next_namestring(&parser_state);
     516                 :            : 
     517                 :          0 :         method_flags = *parser_state.aml++;
     518                 :          0 :         aml_start = parser_state.aml;
     519                 :          0 :         aml_length = ACPI_PTR_DIFF(parser_state.pkg_end, aml_start);
     520                 :            : 
     521                 :            :         /*
     522                 :            :          * Allocate resources up-front. We don't want to have to delete a new
     523                 :            :          * node from the namespace if we cannot allocate memory.
     524                 :            :          */
     525                 :          0 :         aml_buffer = ACPI_ALLOCATE(aml_length);
     526         [ #  # ]:          0 :         if (!aml_buffer) {
     527                 :            :                 return (AE_NO_MEMORY);
     528                 :            :         }
     529                 :            : 
     530                 :          0 :         method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
     531         [ #  # ]:          0 :         if (!method_obj) {
     532                 :          0 :                 ACPI_FREE(aml_buffer);
     533                 :          0 :                 return (AE_NO_MEMORY);
     534                 :            :         }
     535                 :            : 
     536                 :            :         /* Lock namespace for acpi_ns_lookup, we may be creating a new node */
     537                 :            : 
     538                 :          0 :         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
     539         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     540                 :          0 :                 goto error_exit;
     541                 :            :         }
     542                 :            : 
     543                 :            :         /* The lookup either returns an existing node or creates a new one */
     544                 :            : 
     545                 :          0 :         status =
     546                 :          0 :             acpi_ns_lookup(NULL, path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
     547                 :            :                            ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND,
     548                 :            :                            NULL, &node);
     549                 :            : 
     550                 :          0 :         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
     551                 :            : 
     552         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {     /* ns_lookup */
     553         [ #  # ]:          0 :                 if (status != AE_ALREADY_EXISTS) {
     554                 :          0 :                         goto error_exit;
     555                 :            :                 }
     556                 :            : 
     557                 :            :                 /* Node existed previously, make sure it is a method node */
     558                 :            : 
     559         [ #  # ]:          0 :                 if (node->type != ACPI_TYPE_METHOD) {
     560                 :          0 :                         status = AE_TYPE;
     561                 :          0 :                         goto error_exit;
     562                 :            :                 }
     563                 :            :         }
     564                 :            : 
     565                 :            :         /* Copy the method AML to the local buffer */
     566                 :            : 
     567                 :          0 :         memcpy(aml_buffer, aml_start, aml_length);
     568                 :            : 
     569                 :            :         /* Initialize the method object with the new method's information */
     570                 :            : 
     571                 :          0 :         method_obj->method.aml_start = aml_buffer;
     572                 :          0 :         method_obj->method.aml_length = aml_length;
     573                 :            : 
     574                 :          0 :         method_obj->method.param_count = (u8)
     575                 :            :             (method_flags & AML_METHOD_ARG_COUNT);
     576                 :            : 
     577         [ #  # ]:          0 :         if (method_flags & AML_METHOD_SERIALIZED) {
     578                 :          0 :                 method_obj->method.info_flags = ACPI_METHOD_SERIALIZED;
     579                 :            : 
     580                 :          0 :                 method_obj->method.sync_level = (u8)
     581                 :          0 :                     ((method_flags & AML_METHOD_SYNC_LEVEL) >> 4);
     582                 :            :         }
     583                 :            : 
     584                 :            :         /*
     585                 :            :          * Now that it is complete, we can attach the new method object to
     586                 :            :          * the method Node (detaches/deletes any existing object)
     587                 :            :          */
     588                 :          0 :         status = acpi_ns_attach_object(node, method_obj, ACPI_TYPE_METHOD);
     589                 :            : 
     590                 :            :         /*
     591                 :            :          * Flag indicates AML buffer is dynamic, must be deleted later.
     592                 :            :          * Must be set only after attach above.
     593                 :            :          */
     594                 :          0 :         node->flags |= ANOBJ_ALLOCATED_BUFFER;
     595                 :            : 
     596                 :            :         /* Remove local reference to the method object */
     597                 :            : 
     598                 :          0 :         acpi_ut_remove_reference(method_obj);
     599                 :          0 :         return (status);
     600                 :            : 
     601                 :          0 : error_exit:
     602                 :            : 
     603                 :          0 :         ACPI_FREE(aml_buffer);
     604                 :          0 :         ACPI_FREE(method_obj);
     605                 :          0 :         return (status);
     606                 :            : }
     607                 :            : ACPI_EXPORT_SYMBOL(acpi_install_method)

Generated by: LCOV version 1.14