cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

apple.c (4202B)


      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 */
     13static 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 */
     27void acpi_extract_apple_properties(struct acpi_device *adev)
     28{
     29	unsigned int i, j = 0, newsize = 0, numprops, numvalid;
     30	union acpi_object *props, *newprops;
     31	unsigned long *valid = NULL;
     32	void *free_space;
     33
     34	if (!x86_apple_machine)
     35		return;
     36
     37	props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 0,
     38					NULL, ACPI_TYPE_BUFFER);
     39	if (!props)
     40		return;
     41
     42	if (!props->buffer.length)
     43		goto out_free;
     44
     45	if (props->buffer.pointer[0] != 3) {
     46		acpi_handle_info(adev->handle, FW_INFO
     47				 "unsupported properties version %*ph\n",
     48				 props->buffer.length, props->buffer.pointer);
     49		goto out_free;
     50	}
     51
     52	ACPI_FREE(props);
     53	props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 1,
     54					NULL, ACPI_TYPE_PACKAGE);
     55	if (!props)
     56		return;
     57
     58	numprops = props->package.count / 2;
     59	if (!numprops)
     60		goto out_free;
     61
     62	valid = bitmap_zalloc(numprops, GFP_KERNEL);
     63	if (!valid)
     64		goto out_free;
     65
     66	/* newsize = key length + value length of each tuple */
     67	for (i = 0; i < numprops; i++) {
     68		union acpi_object *key = &props->package.elements[i * 2];
     69		union acpi_object *val = &props->package.elements[i * 2 + 1];
     70
     71		if ( key->type != ACPI_TYPE_STRING ||
     72		    (val->type != ACPI_TYPE_INTEGER &&
     73		     val->type != ACPI_TYPE_BUFFER))
     74			continue; /* skip invalid properties */
     75
     76		__set_bit(i, valid);
     77		newsize += key->string.length + 1;
     78		if ( val->type == ACPI_TYPE_BUFFER)
     79			newsize += val->buffer.length;
     80	}
     81
     82	numvalid = bitmap_weight(valid, numprops);
     83	if (numprops > numvalid)
     84		acpi_handle_info(adev->handle, FW_INFO
     85				 "skipped %u properties: wrong type\n",
     86				 numprops - numvalid);
     87	if (numvalid == 0)
     88		goto out_free;
     89
     90	/* newsize += top-level package + 3 objects for each key/value tuple */
     91	newsize	+= (1 + 3 * numvalid) * sizeof(union acpi_object);
     92	newprops = ACPI_ALLOCATE_ZEROED(newsize);
     93	if (!newprops)
     94		goto out_free;
     95
     96	/* layout: top-level package | packages | key/value tuples | strings */
     97	newprops->type = ACPI_TYPE_PACKAGE;
     98	newprops->package.count = numvalid;
     99	newprops->package.elements = &newprops[1];
    100	free_space = &newprops[1 + 3 * numvalid];
    101
    102	for_each_set_bit(i, valid, numprops) {
    103		union acpi_object *key = &props->package.elements[i * 2];
    104		union acpi_object *val = &props->package.elements[i * 2 + 1];
    105		unsigned int k = 1 + numvalid + j * 2; /* index into newprops */
    106		unsigned int v = k + 1;
    107
    108		newprops[1 + j].type = ACPI_TYPE_PACKAGE;
    109		newprops[1 + j].package.count = 2;
    110		newprops[1 + j].package.elements = &newprops[k];
    111
    112		newprops[k].type = ACPI_TYPE_STRING;
    113		newprops[k].string.length = key->string.length;
    114		newprops[k].string.pointer = free_space;
    115		memcpy(free_space, key->string.pointer, key->string.length);
    116		free_space += key->string.length + 1;
    117
    118		newprops[v].type = val->type;
    119		if (val->type == ACPI_TYPE_INTEGER) {
    120			newprops[v].integer.value = val->integer.value;
    121		} else {
    122			newprops[v].buffer.length = val->buffer.length;
    123			newprops[v].buffer.pointer = free_space;
    124			memcpy(free_space, val->buffer.pointer,
    125			       val->buffer.length);
    126			free_space += val->buffer.length;
    127		}
    128		j++; /* count valid properties */
    129	}
    130	WARN_ON(free_space != (void *)newprops + newsize);
    131
    132	adev->data.pointer = newprops;
    133	acpi_data_add_props(&adev->data, &apple_prp_guid, newprops);
    134
    135out_free:
    136	ACPI_FREE(props);
    137	bitmap_free(valid);
    138}