LCOV - code coverage report
Current view: top level - drivers/acpi/acpica - utids.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 97 139 69.8 %
Date: 2022-03-28 13:20:08 Functions: 4 4 100.0 %
Branches: 25 49 51.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
       2                 :            : /******************************************************************************
       3                 :            :  *
       4                 :            :  * Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
       5                 :            :  *
       6                 :            :  * Copyright (C) 2000 - 2020, Intel Corp.
       7                 :            :  *
       8                 :            :  *****************************************************************************/
       9                 :            : 
      10                 :            : #include <acpi/acpi.h>
      11                 :            : #include "accommon.h"
      12                 :            : #include "acinterp.h"
      13                 :            : 
      14                 :            : #define _COMPONENT          ACPI_UTILITIES
      15                 :            : ACPI_MODULE_NAME("utids")
      16                 :            : 
      17                 :            : /*******************************************************************************
      18                 :            :  *
      19                 :            :  * FUNCTION:    acpi_ut_execute_HID
      20                 :            :  *
      21                 :            :  * PARAMETERS:  device_node         - Node for the device
      22                 :            :  *              return_id           - Where the string HID is returned
      23                 :            :  *
      24                 :            :  * RETURN:      Status
      25                 :            :  *
      26                 :            :  * DESCRIPTION: Executes the _HID control method that returns the hardware
      27                 :            :  *              ID of the device. The HID is either an 32-bit encoded EISAID
      28                 :            :  *              Integer or a String. A string is always returned. An EISAID
      29                 :            :  *              is converted to a string.
      30                 :            :  *
      31                 :            :  *              NOTE: Internal function, no parameter validation
      32                 :            :  *
      33                 :            :  ******************************************************************************/
      34                 :            : acpi_status
      35                 :       8310 : acpi_ut_execute_HID(struct acpi_namespace_node *device_node,
      36                 :            :                     struct acpi_pnp_device_id **return_id)
      37                 :            : {
      38                 :       8310 :         union acpi_operand_object *obj_desc;
      39                 :       8310 :         struct acpi_pnp_device_id *hid;
      40                 :       8310 :         u32 length;
      41                 :       8310 :         acpi_status status;
      42                 :            : 
      43                 :       8310 :         ACPI_FUNCTION_TRACE(ut_execute_HID);
      44                 :            : 
      45                 :       8310 :         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID,
      46                 :            :                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
      47                 :            :                                          &obj_desc);
      48         [ +  + ]:       8310 :         if (ACPI_FAILURE(status)) {
      49                 :            :                 return_ACPI_STATUS(status);
      50                 :            :         }
      51                 :            : 
      52                 :            :         /* Get the size of the String to be returned, includes null terminator */
      53                 :            : 
      54         [ +  + ]:       2880 :         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
      55                 :            :                 length = ACPI_EISAID_STRING_SIZE;
      56                 :            :         } else {
      57                 :        600 :                 length = obj_desc->string.length + 1;
      58                 :            :         }
      59                 :            : 
      60                 :            :         /* Allocate a buffer for the HID */
      61                 :            : 
      62                 :       2880 :         hid =
      63                 :       2880 :             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
      64                 :            :                                  (acpi_size)length);
      65         [ -  + ]:       2880 :         if (!hid) {
      66                 :          0 :                 status = AE_NO_MEMORY;
      67                 :          0 :                 goto cleanup;
      68                 :            :         }
      69                 :            : 
      70                 :            :         /* Area for the string starts after PNP_DEVICE_ID struct */
      71                 :            : 
      72                 :       2880 :         hid->string =
      73                 :       2880 :             ACPI_ADD_PTR(char, hid, sizeof(struct acpi_pnp_device_id));
      74                 :            : 
      75                 :            :         /* Convert EISAID to a string or simply copy existing string */
      76                 :            : 
      77         [ +  + ]:       2880 :         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
      78                 :       2280 :                 acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value);
      79                 :            :         } else {
      80                 :        600 :                 strcpy(hid->string, obj_desc->string.pointer);
      81                 :            :         }
      82                 :            : 
      83                 :       2880 :         hid->length = length;
      84                 :       2880 :         *return_id = hid;
      85                 :            : 
      86                 :       2880 : cleanup:
      87                 :            : 
      88                 :            :         /* On exit, we must delete the return object */
      89                 :            : 
      90                 :       2880 :         acpi_ut_remove_reference(obj_desc);
      91                 :       2880 :         return_ACPI_STATUS(status);
      92                 :            : }
      93                 :            : 
      94                 :            : /*******************************************************************************
      95                 :            :  *
      96                 :            :  * FUNCTION:    acpi_ut_execute_UID
      97                 :            :  *
      98                 :            :  * PARAMETERS:  device_node         - Node for the device
      99                 :            :  *              return_id           - Where the string UID is returned
     100                 :            :  *
     101                 :            :  * RETURN:      Status
     102                 :            :  *
     103                 :            :  * DESCRIPTION: Executes the _UID control method that returns the unique
     104                 :            :  *              ID of the device. The UID is either a 64-bit Integer (NOT an
     105                 :            :  *              EISAID) or a string. Always returns a string. A 64-bit integer
     106                 :            :  *              is converted to a decimal string.
     107                 :            :  *
     108                 :            :  *              NOTE: Internal function, no parameter validation
     109                 :            :  *
     110                 :            :  ******************************************************************************/
     111                 :            : 
     112                 :            : acpi_status
     113                 :       3300 : acpi_ut_execute_UID(struct acpi_namespace_node *device_node,
     114                 :            :                     struct acpi_pnp_device_id **return_id)
     115                 :            : {
     116                 :       3300 :         union acpi_operand_object *obj_desc;
     117                 :       3300 :         struct acpi_pnp_device_id *uid;
     118                 :       3300 :         u32 length;
     119                 :       3300 :         acpi_status status;
     120                 :            : 
     121                 :       3300 :         ACPI_FUNCTION_TRACE(ut_execute_UID);
     122                 :            : 
     123                 :       3300 :         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID,
     124                 :            :                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING,
     125                 :            :                                          &obj_desc);
     126         [ +  + ]:       3300 :         if (ACPI_FAILURE(status)) {
     127                 :            :                 return_ACPI_STATUS(status);
     128                 :            :         }
     129                 :            : 
     130                 :            :         /* Get the size of the String to be returned, includes null terminator */
     131                 :            : 
     132         [ +  + ]:        720 :         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
     133                 :            :                 length = ACPI_MAX64_DECIMAL_DIGITS + 1;
     134                 :            :         } else {
     135                 :        180 :                 length = obj_desc->string.length + 1;
     136                 :            :         }
     137                 :            : 
     138                 :            :         /* Allocate a buffer for the UID */
     139                 :            : 
     140                 :        720 :         uid =
     141                 :        720 :             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
     142                 :            :                                  (acpi_size)length);
     143         [ -  + ]:        720 :         if (!uid) {
     144                 :          0 :                 status = AE_NO_MEMORY;
     145                 :          0 :                 goto cleanup;
     146                 :            :         }
     147                 :            : 
     148                 :            :         /* Area for the string starts after PNP_DEVICE_ID struct */
     149                 :            : 
     150                 :        720 :         uid->string =
     151                 :        720 :             ACPI_ADD_PTR(char, uid, sizeof(struct acpi_pnp_device_id));
     152                 :            : 
     153                 :            :         /* Convert an Integer to string, or just copy an existing string */
     154                 :            : 
     155         [ +  + ]:        720 :         if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
     156                 :        540 :                 acpi_ex_integer_to_string(uid->string, obj_desc->integer.value);
     157                 :            :         } else {
     158                 :        180 :                 strcpy(uid->string, obj_desc->string.pointer);
     159                 :            :         }
     160                 :            : 
     161                 :        720 :         uid->length = length;
     162                 :        720 :         *return_id = uid;
     163                 :            : 
     164                 :        720 : cleanup:
     165                 :            : 
     166                 :            :         /* On exit, we must delete the return object */
     167                 :            : 
     168                 :        720 :         acpi_ut_remove_reference(obj_desc);
     169                 :        720 :         return_ACPI_STATUS(status);
     170                 :            : }
     171                 :            : 
     172                 :            : /*******************************************************************************
     173                 :            :  *
     174                 :            :  * FUNCTION:    acpi_ut_execute_CID
     175                 :            :  *
     176                 :            :  * PARAMETERS:  device_node         - Node for the device
     177                 :            :  *              return_cid_list     - Where the CID list is returned
     178                 :            :  *
     179                 :            :  * RETURN:      Status, list of CID strings
     180                 :            :  *
     181                 :            :  * DESCRIPTION: Executes the _CID control method that returns one or more
     182                 :            :  *              compatible hardware IDs for the device.
     183                 :            :  *
     184                 :            :  *              NOTE: Internal function, no parameter validation
     185                 :            :  *
     186                 :            :  * A _CID method can return either a single compatible ID or a package of
     187                 :            :  * compatible IDs. Each compatible ID can be one of the following:
     188                 :            :  * 1) Integer (32 bit compressed EISA ID) or
     189                 :            :  * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss")
     190                 :            :  *
     191                 :            :  * The Integer CIDs are converted to string format by this function.
     192                 :            :  *
     193                 :            :  ******************************************************************************/
     194                 :            : 
     195                 :            : acpi_status
     196                 :       5010 : acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
     197                 :            :                     struct acpi_pnp_device_id_list **return_cid_list)
     198                 :            : {
     199                 :       5010 :         union acpi_operand_object **cid_objects;
     200                 :       5010 :         union acpi_operand_object *obj_desc;
     201                 :       5010 :         struct acpi_pnp_device_id_list *cid_list;
     202                 :       5010 :         char *next_id_string;
     203                 :       5010 :         u32 string_area_size;
     204                 :       5010 :         u32 length;
     205                 :       5010 :         u32 cid_list_size;
     206                 :       5010 :         acpi_status status;
     207                 :       5010 :         u32 count;
     208                 :       5010 :         u32 i;
     209                 :            : 
     210                 :       5010 :         ACPI_FUNCTION_TRACE(ut_execute_CID);
     211                 :            : 
     212                 :            :         /* Evaluate the _CID method for this device */
     213                 :            : 
     214                 :       5010 :         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID,
     215                 :            :                                          ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING
     216                 :            :                                          | ACPI_BTYPE_PACKAGE, &obj_desc);
     217         [ +  + ]:       5010 :         if (ACPI_FAILURE(status)) {
     218                 :            :                 return_ACPI_STATUS(status);
     219                 :            :         }
     220                 :            : 
     221                 :            :         /*
     222                 :            :          * Get the count and size of the returned _CIDs. _CID can return either
     223                 :            :          * a Package of Integers/Strings or a single Integer or String.
     224                 :            :          * Note: This section also validates that all CID elements are of the
     225                 :            :          * correct type (Integer or String).
     226                 :            :          */
     227         [ -  + ]:        150 :         if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
     228                 :          0 :                 count = obj_desc->package.count;
     229                 :          0 :                 cid_objects = obj_desc->package.elements;
     230                 :            :         } else {                /* Single Integer or String CID */
     231                 :            : 
     232                 :            :                 count = 1;
     233                 :            :                 cid_objects = &obj_desc;
     234                 :            :         }
     235                 :            : 
     236                 :        150 :         string_area_size = 0;
     237         [ +  + ]:        300 :         for (i = 0; i < count; i++) {
     238                 :            : 
     239                 :            :                 /* String lengths include null terminator */
     240                 :            : 
     241      [ +  -  - ]:        150 :                 switch (cid_objects[i]->common.type) {
     242                 :        150 :                 case ACPI_TYPE_INTEGER:
     243                 :            : 
     244                 :        150 :                         string_area_size += ACPI_EISAID_STRING_SIZE;
     245                 :        150 :                         break;
     246                 :            : 
     247                 :          0 :                 case ACPI_TYPE_STRING:
     248                 :            : 
     249                 :          0 :                         string_area_size += cid_objects[i]->string.length + 1;
     250                 :          0 :                         break;
     251                 :            : 
     252                 :          0 :                 default:
     253                 :            : 
     254                 :          0 :                         status = AE_TYPE;
     255                 :          0 :                         goto cleanup;
     256                 :            :                 }
     257                 :            :         }
     258                 :            : 
     259                 :            :         /*
     260                 :            :          * Now that we know the length of the CIDs, allocate return buffer:
     261                 :            :          * 1) Size of the base structure +
     262                 :            :          * 2) Size of the CID PNP_DEVICE_ID array +
     263                 :            :          * 3) Size of the actual CID strings
     264                 :            :          */
     265                 :        150 :         cid_list_size = sizeof(struct acpi_pnp_device_id_list) +
     266                 :        150 :             ((count - 1) * sizeof(struct acpi_pnp_device_id)) +
     267                 :            :             string_area_size;
     268                 :            : 
     269                 :        150 :         cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size);
     270         [ -  + ]:        150 :         if (!cid_list) {
     271                 :          0 :                 status = AE_NO_MEMORY;
     272                 :          0 :                 goto cleanup;
     273                 :            :         }
     274                 :            : 
     275                 :            :         /* Area for CID strings starts after the CID PNP_DEVICE_ID array */
     276                 :            : 
     277                 :        150 :         next_id_string = ACPI_CAST_PTR(char, cid_list->ids) +
     278                 :        150 :             ((acpi_size)count * sizeof(struct acpi_pnp_device_id));
     279                 :            : 
     280                 :            :         /* Copy/convert the CIDs to the return buffer */
     281                 :            : 
     282         [ +  + ]:        300 :         for (i = 0; i < count; i++) {
     283         [ +  - ]:        150 :                 if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) {
     284                 :            : 
     285                 :            :                         /* Convert the Integer (EISAID) CID to a string */
     286                 :            : 
     287                 :        150 :                         acpi_ex_eisa_id_to_string(next_id_string,
     288                 :            :                                                   cid_objects[i]->integer.
     289                 :            :                                                   value);
     290                 :        150 :                         length = ACPI_EISAID_STRING_SIZE;
     291                 :            :                 } else {        /* ACPI_TYPE_STRING */
     292                 :            :                         /* Copy the String CID from the returned object */
     293                 :          0 :                         strcpy(next_id_string, cid_objects[i]->string.pointer);
     294                 :          0 :                         length = cid_objects[i]->string.length + 1;
     295                 :            :                 }
     296                 :            : 
     297                 :        150 :                 cid_list->ids[i].string = next_id_string;
     298                 :        150 :                 cid_list->ids[i].length = length;
     299                 :        150 :                 next_id_string += length;
     300                 :            :         }
     301                 :            : 
     302                 :            :         /* Finish the CID list */
     303                 :            : 
     304                 :        150 :         cid_list->count = count;
     305                 :        150 :         cid_list->list_size = cid_list_size;
     306                 :        150 :         *return_cid_list = cid_list;
     307                 :            : 
     308                 :        150 : cleanup:
     309                 :            : 
     310                 :            :         /* On exit, we must delete the _CID return object */
     311                 :            : 
     312                 :        150 :         acpi_ut_remove_reference(obj_desc);
     313                 :        150 :         return_ACPI_STATUS(status);
     314                 :            : }
     315                 :            : 
     316                 :            : /*******************************************************************************
     317                 :            :  *
     318                 :            :  * FUNCTION:    acpi_ut_execute_CLS
     319                 :            :  *
     320                 :            :  * PARAMETERS:  device_node         - Node for the device
     321                 :            :  *              return_id           - Where the _CLS is returned
     322                 :            :  *
     323                 :            :  * RETURN:      Status
     324                 :            :  *
     325                 :            :  * DESCRIPTION: Executes the _CLS control method that returns PCI-defined
     326                 :            :  *              class code of the device. The _CLS value is always a package
     327                 :            :  *              containing PCI class information as a list of integers.
     328                 :            :  *              The returned string has format "BBSSPP", where:
     329                 :            :  *                BB = Base-class code
     330                 :            :  *                SS = Sub-class code
     331                 :            :  *                PP = Programming Interface code
     332                 :            :  *
     333                 :            :  ******************************************************************************/
     334                 :            : 
     335                 :            : acpi_status
     336                 :       3300 : acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
     337                 :            :                     struct acpi_pnp_device_id **return_id)
     338                 :            : {
     339                 :       3300 :         union acpi_operand_object *obj_desc;
     340                 :       3300 :         union acpi_operand_object **cls_objects;
     341                 :       3300 :         u32 count;
     342                 :       3300 :         struct acpi_pnp_device_id *cls;
     343                 :       3300 :         u32 length;
     344                 :       3300 :         acpi_status status;
     345                 :       3300 :         u8 class_code[3] = { 0, 0, 0 };
     346                 :            : 
     347                 :       3300 :         ACPI_FUNCTION_TRACE(ut_execute_CLS);
     348                 :            : 
     349                 :       3300 :         status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS,
     350                 :            :                                          ACPI_BTYPE_PACKAGE, &obj_desc);
     351         [ -  + ]:       3300 :         if (ACPI_FAILURE(status)) {
     352                 :            :                 return_ACPI_STATUS(status);
     353                 :            :         }
     354                 :            : 
     355                 :            :         /* Get the size of the String to be returned, includes null terminator */
     356                 :            : 
     357                 :          0 :         length = ACPI_PCICLS_STRING_SIZE;
     358                 :          0 :         cls_objects = obj_desc->package.elements;
     359                 :          0 :         count = obj_desc->package.count;
     360                 :            : 
     361         [ #  # ]:          0 :         if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
     362         [ #  # ]:          0 :                 if (count > 0
     363         [ #  # ]:          0 :                     && cls_objects[0]->common.type == ACPI_TYPE_INTEGER) {
     364                 :          0 :                         class_code[0] = (u8)cls_objects[0]->integer.value;
     365                 :            :                 }
     366         [ #  # ]:          0 :                 if (count > 1
     367         [ #  # ]:          0 :                     && cls_objects[1]->common.type == ACPI_TYPE_INTEGER) {
     368                 :          0 :                         class_code[1] = (u8)cls_objects[1]->integer.value;
     369                 :            :                 }
     370         [ #  # ]:          0 :                 if (count > 2
     371         [ #  # ]:          0 :                     && cls_objects[2]->common.type == ACPI_TYPE_INTEGER) {
     372                 :          0 :                         class_code[2] = (u8)cls_objects[2]->integer.value;
     373                 :            :                 }
     374                 :            :         }
     375                 :            : 
     376                 :            :         /* Allocate a buffer for the CLS */
     377                 :            : 
     378                 :          0 :         cls =
     379                 :          0 :             ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
     380                 :            :                                  (acpi_size)length);
     381         [ #  # ]:          0 :         if (!cls) {
     382                 :          0 :                 status = AE_NO_MEMORY;
     383                 :          0 :                 goto cleanup;
     384                 :            :         }
     385                 :            : 
     386                 :            :         /* Area for the string starts after PNP_DEVICE_ID struct */
     387                 :            : 
     388                 :          0 :         cls->string =
     389                 :          0 :             ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id));
     390                 :            : 
     391                 :            :         /* Simply copy existing string */
     392                 :            : 
     393                 :          0 :         acpi_ex_pci_cls_to_string(cls->string, class_code);
     394                 :          0 :         cls->length = length;
     395                 :          0 :         *return_id = cls;
     396                 :            : 
     397                 :          0 : cleanup:
     398                 :            : 
     399                 :            :         /* On exit, we must delete the return object */
     400                 :            : 
     401                 :          0 :         acpi_ut_remove_reference(obj_desc);
     402                 :          0 :         return_ACPI_STATUS(status);
     403                 :            : }

Generated by: LCOV version 1.14