LCOV - code coverage report
Current view: top level - drivers/acpi/x86 - apple.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 6 73 8.2 %
Date: 2022-03-28 13:20:08 Functions: 1 1 100.0 %
Branches: 1 36 2.8 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * apple.c - Apple ACPI quirks
       4                 :            :  * Copyright (C) 2017 Lukas Wunner <lukas@wunner.de>
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <linux/acpi.h>
       8                 :            : #include <linux/bitmap.h>
       9                 :            : #include <linux/platform_data/x86/apple.h>
      10                 :            : #include <linux/uuid.h>
      11                 :            : 
      12                 :            : /* Apple _DSM device properties GUID */
      13                 :            : static const guid_t apple_prp_guid =
      14                 :            :         GUID_INIT(0xa0b5b7c6, 0x1318, 0x441c,
      15                 :            :                   0xb0, 0xc9, 0xfe, 0x69, 0x5e, 0xaf, 0x94, 0x9b);
      16                 :            : 
      17                 :            : /**
      18                 :            :  * acpi_extract_apple_properties - retrieve and convert Apple _DSM properties
      19                 :            :  * @adev: ACPI device for which to retrieve the properties
      20                 :            :  *
      21                 :            :  * Invoke Apple's custom _DSM once to check the protocol version and once more
      22                 :            :  * to retrieve the properties.  They are marshalled up in a single package as
      23                 :            :  * alternating key/value elements, unlike _DSD which stores them as a package
      24                 :            :  * of 2-element packages.  Convert to _DSD format and make them available under
      25                 :            :  * the primary fwnode.
      26                 :            :  */
      27                 :       1710 : void acpi_extract_apple_properties(struct acpi_device *adev)
      28                 :            : {
      29                 :       1710 :         unsigned int i, j = 0, newsize = 0, numprops, numvalid;
      30                 :       1710 :         union acpi_object *props, *newprops;
      31                 :       1710 :         unsigned long *valid = NULL;
      32                 :       1710 :         void *free_space;
      33                 :            : 
      34         [ -  + ]:       1710 :         if (!x86_apple_machine)
      35                 :            :                 return;
      36                 :            : 
      37                 :          0 :         props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 0,
      38                 :            :                                         NULL, ACPI_TYPE_BUFFER);
      39         [ #  # ]:          0 :         if (!props)
      40                 :            :                 return;
      41                 :            : 
      42         [ #  # ]:          0 :         if (!props->buffer.length)
      43                 :          0 :                 goto out_free;
      44                 :            : 
      45         [ #  # ]:          0 :         if (props->buffer.pointer[0] != 3) {
      46                 :          0 :                 acpi_handle_info(adev->handle, FW_INFO
      47                 :            :                                  "unsupported properties version %*ph\n",
      48                 :            :                                  props->buffer.length, props->buffer.pointer);
      49                 :          0 :                 goto out_free;
      50                 :            :         }
      51                 :            : 
      52                 :          0 :         ACPI_FREE(props);
      53                 :          0 :         props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 1,
      54                 :            :                                         NULL, ACPI_TYPE_PACKAGE);
      55         [ #  # ]:          0 :         if (!props)
      56                 :            :                 return;
      57                 :            : 
      58                 :          0 :         numprops = props->package.count / 2;
      59         [ #  # ]:          0 :         if (!numprops)
      60                 :          0 :                 goto out_free;
      61                 :            : 
      62                 :          0 :         valid = bitmap_zalloc(numprops, GFP_KERNEL);
      63         [ #  # ]:          0 :         if (!valid)
      64                 :          0 :                 goto out_free;
      65                 :            : 
      66                 :            :         /* newsize = key length + value length of each tuple */
      67         [ #  # ]:          0 :         for (i = 0; i < numprops; i++) {
      68                 :          0 :                 union acpi_object *key = &props->package.elements[i * 2];
      69                 :          0 :                 union acpi_object *val = &props->package.elements[i * 2 + 1];
      70                 :            : 
      71         [ #  # ]:          0 :                 if ( key->type != ACPI_TYPE_STRING ||
      72         [ #  # ]:          0 :                     (val->type != ACPI_TYPE_INTEGER &&
      73                 :            :                      val->type != ACPI_TYPE_BUFFER))
      74                 :          0 :                         continue; /* skip invalid properties */
      75                 :            : 
      76                 :          0 :                 __set_bit(i, valid);
      77                 :          0 :                 newsize += key->string.length + 1;
      78         [ #  # ]:          0 :                 if ( val->type == ACPI_TYPE_BUFFER)
      79                 :          0 :                         newsize += val->buffer.length;
      80                 :            :         }
      81                 :            : 
      82         [ #  # ]:          0 :         numvalid = bitmap_weight(valid, numprops);
      83         [ #  # ]:          0 :         if (numprops > numvalid)
      84                 :          0 :                 acpi_handle_info(adev->handle, FW_INFO
      85                 :            :                                  "skipped %u properties: wrong type\n",
      86                 :            :                                  numprops - numvalid);
      87         [ #  # ]:          0 :         if (numvalid == 0)
      88                 :          0 :                 goto out_free;
      89                 :            : 
      90                 :            :         /* newsize += top-level package + 3 objects for each key/value tuple */
      91                 :          0 :         newsize += (1 + 3 * numvalid) * sizeof(union acpi_object);
      92                 :          0 :         newprops = ACPI_ALLOCATE_ZEROED(newsize);
      93         [ #  # ]:          0 :         if (!newprops)
      94                 :          0 :                 goto out_free;
      95                 :            : 
      96                 :            :         /* layout: top-level package | packages | key/value tuples | strings */
      97                 :          0 :         newprops->type = ACPI_TYPE_PACKAGE;
      98                 :          0 :         newprops->package.count = numvalid;
      99                 :          0 :         newprops->package.elements = &newprops[1];
     100                 :          0 :         free_space = &newprops[1 + 3 * numvalid];
     101                 :            : 
     102         [ #  # ]:          0 :         for_each_set_bit(i, valid, numprops) {
     103                 :          0 :                 union acpi_object *key = &props->package.elements[i * 2];
     104                 :          0 :                 union acpi_object *val = &props->package.elements[i * 2 + 1];
     105                 :          0 :                 unsigned int k = 1 + numvalid + j * 2; /* index into newprops */
     106                 :          0 :                 unsigned int v = k + 1;
     107                 :            : 
     108                 :          0 :                 newprops[1 + j].type = ACPI_TYPE_PACKAGE;
     109                 :          0 :                 newprops[1 + j].package.count = 2;
     110                 :          0 :                 newprops[1 + j].package.elements = &newprops[k];
     111                 :            : 
     112                 :          0 :                 newprops[k].type = ACPI_TYPE_STRING;
     113                 :          0 :                 newprops[k].string.length = key->string.length;
     114                 :          0 :                 newprops[k].string.pointer = free_space;
     115                 :          0 :                 memcpy(free_space, key->string.pointer, key->string.length);
     116                 :          0 :                 free_space += key->string.length + 1;
     117                 :            : 
     118                 :          0 :                 newprops[v].type = val->type;
     119         [ #  # ]:          0 :                 if (val->type == ACPI_TYPE_INTEGER) {
     120                 :          0 :                         newprops[v].integer.value = val->integer.value;
     121                 :            :                 } else {
     122                 :          0 :                         newprops[v].buffer.length = val->buffer.length;
     123                 :          0 :                         newprops[v].buffer.pointer = free_space;
     124                 :          0 :                         memcpy(free_space, val->buffer.pointer,
     125                 :          0 :                                val->buffer.length);
     126                 :          0 :                         free_space += val->buffer.length;
     127                 :            :                 }
     128                 :          0 :                 j++; /* count valid properties */
     129                 :            :         }
     130         [ #  # ]:          0 :         WARN_ON(free_space != (void *)newprops + newsize);
     131                 :            : 
     132                 :          0 :         adev->data.pointer = newprops;
     133                 :          0 :         acpi_data_add_props(&adev->data, &apple_prp_guid, newprops);
     134                 :            : 
     135                 :          0 : out_free:
     136                 :          0 :         ACPI_FREE(props);
     137                 :          0 :         bitmap_free(valid);
     138                 :            : }

Generated by: LCOV version 1.14