0001
0002
0003
0004
0005
0006
0007 #include <linux/acpi.h>
0008 #include <linux/bitmap.h>
0009 #include <linux/platform_data/x86/apple.h>
0010 #include <linux/uuid.h>
0011
0012
0013 static const guid_t apple_prp_guid =
0014 GUID_INIT(0xa0b5b7c6, 0x1318, 0x441c,
0015 0xb0, 0xc9, 0xfe, 0x69, 0x5e, 0xaf, 0x94, 0x9b);
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 void acpi_extract_apple_properties(struct acpi_device *adev)
0028 {
0029 unsigned int i, j = 0, newsize = 0, numprops, numvalid;
0030 union acpi_object *props, *newprops;
0031 unsigned long *valid = NULL;
0032 void *free_space;
0033
0034 if (!x86_apple_machine)
0035 return;
0036
0037 props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 0,
0038 NULL, ACPI_TYPE_BUFFER);
0039 if (!props)
0040 return;
0041
0042 if (!props->buffer.length)
0043 goto out_free;
0044
0045 if (props->buffer.pointer[0] != 3) {
0046 acpi_handle_info(adev->handle, FW_INFO
0047 "unsupported properties version %*ph\n",
0048 props->buffer.length, props->buffer.pointer);
0049 goto out_free;
0050 }
0051
0052 ACPI_FREE(props);
0053 props = acpi_evaluate_dsm_typed(adev->handle, &apple_prp_guid, 1, 1,
0054 NULL, ACPI_TYPE_PACKAGE);
0055 if (!props)
0056 return;
0057
0058 numprops = props->package.count / 2;
0059 if (!numprops)
0060 goto out_free;
0061
0062 valid = bitmap_zalloc(numprops, GFP_KERNEL);
0063 if (!valid)
0064 goto out_free;
0065
0066
0067 for (i = 0; i < numprops; i++) {
0068 union acpi_object *key = &props->package.elements[i * 2];
0069 union acpi_object *val = &props->package.elements[i * 2 + 1];
0070
0071 if ( key->type != ACPI_TYPE_STRING ||
0072 (val->type != ACPI_TYPE_INTEGER &&
0073 val->type != ACPI_TYPE_BUFFER))
0074 continue;
0075
0076 __set_bit(i, valid);
0077 newsize += key->string.length + 1;
0078 if ( val->type == ACPI_TYPE_BUFFER)
0079 newsize += val->buffer.length;
0080 }
0081
0082 numvalid = bitmap_weight(valid, numprops);
0083 if (numprops > numvalid)
0084 acpi_handle_info(adev->handle, FW_INFO
0085 "skipped %u properties: wrong type\n",
0086 numprops - numvalid);
0087 if (numvalid == 0)
0088 goto out_free;
0089
0090
0091 newsize += (1 + 3 * numvalid) * sizeof(union acpi_object);
0092 newprops = ACPI_ALLOCATE_ZEROED(newsize);
0093 if (!newprops)
0094 goto out_free;
0095
0096
0097 newprops->type = ACPI_TYPE_PACKAGE;
0098 newprops->package.count = numvalid;
0099 newprops->package.elements = &newprops[1];
0100 free_space = &newprops[1 + 3 * numvalid];
0101
0102 for_each_set_bit(i, valid, numprops) {
0103 union acpi_object *key = &props->package.elements[i * 2];
0104 union acpi_object *val = &props->package.elements[i * 2 + 1];
0105 unsigned int k = 1 + numvalid + j * 2;
0106 unsigned int v = k + 1;
0107
0108 newprops[1 + j].type = ACPI_TYPE_PACKAGE;
0109 newprops[1 + j].package.count = 2;
0110 newprops[1 + j].package.elements = &newprops[k];
0111
0112 newprops[k].type = ACPI_TYPE_STRING;
0113 newprops[k].string.length = key->string.length;
0114 newprops[k].string.pointer = free_space;
0115 memcpy(free_space, key->string.pointer, key->string.length);
0116 free_space += key->string.length + 1;
0117
0118 newprops[v].type = val->type;
0119 if (val->type == ACPI_TYPE_INTEGER) {
0120 newprops[v].integer.value = val->integer.value;
0121 } else {
0122 newprops[v].buffer.length = val->buffer.length;
0123 newprops[v].buffer.pointer = free_space;
0124 memcpy(free_space, val->buffer.pointer,
0125 val->buffer.length);
0126 free_space += val->buffer.length;
0127 }
0128 j++;
0129 }
0130 WARN_ON(free_space != (void *)newprops + newsize);
0131
0132 adev->data.pointer = newprops;
0133 acpi_data_add_props(&adev->data, &apple_prp_guid, newprops);
0134
0135 out_free:
0136 ACPI_FREE(props);
0137 bitmap_free(valid);
0138 }