| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * ACPI-WMI mapping driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 11 | 12 | * WMI bus infrastructure by Andrew Lutomirski and Darren Hart: |
|---|
| 12 | 13 | * Copyright (C) 2015 Andrew Lutomirski |
|---|
| 13 | 14 | * Copyright (C) 2017 VMware, Inc. All Rights Reserved. |
|---|
| 14 | | - * |
|---|
| 15 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 16 | | - * |
|---|
| 17 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 18 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 19 | | - * the Free Software Foundation; either version 2 of the License, or (at |
|---|
| 20 | | - * your option) any later version. |
|---|
| 21 | | - * |
|---|
| 22 | | - * This program is distributed in the hope that it will be useful, but |
|---|
| 23 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 24 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|---|
| 25 | | - * General Public License for more details. |
|---|
| 26 | | - * |
|---|
| 27 | | - * You should have received a copy of the GNU General Public License along |
|---|
| 28 | | - * with this program; if not, write to the Free Software Foundation, Inc., |
|---|
| 29 | | - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|---|
| 30 | | - * |
|---|
| 31 | | - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 32 | 15 | */ |
|---|
| 33 | 16 | |
|---|
| 34 | 17 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
|---|
| .. | .. |
|---|
| 46 | 29 | #include <linux/uaccess.h> |
|---|
| 47 | 30 | #include <linux/uuid.h> |
|---|
| 48 | 31 | #include <linux/wmi.h> |
|---|
| 32 | +#include <linux/fs.h> |
|---|
| 49 | 33 | #include <uapi/linux/wmi.h> |
|---|
| 50 | 34 | |
|---|
| 51 | 35 | ACPI_MODULE_NAME("wmi"); |
|---|
| .. | .. |
|---|
| 127 | 111 | |
|---|
| 128 | 112 | static bool find_guid(const char *guid_string, struct wmi_block **out) |
|---|
| 129 | 113 | { |
|---|
| 130 | | - uuid_le guid_input; |
|---|
| 114 | + guid_t guid_input; |
|---|
| 131 | 115 | struct wmi_block *wblock; |
|---|
| 132 | 116 | struct guid_block *block; |
|---|
| 133 | 117 | |
|---|
| 134 | | - if (uuid_le_to_bin(guid_string, &guid_input)) |
|---|
| 118 | + if (guid_parse(guid_string, &guid_input)) |
|---|
| 135 | 119 | return false; |
|---|
| 136 | 120 | |
|---|
| 137 | 121 | list_for_each_entry(wblock, &wmi_block_list, list) { |
|---|
| .. | .. |
|---|
| 144 | 128 | } |
|---|
| 145 | 129 | } |
|---|
| 146 | 130 | return false; |
|---|
| 131 | +} |
|---|
| 132 | + |
|---|
| 133 | +static const void *find_guid_context(struct wmi_block *wblock, |
|---|
| 134 | + struct wmi_driver *wdriver) |
|---|
| 135 | +{ |
|---|
| 136 | + const struct wmi_device_id *id; |
|---|
| 137 | + guid_t guid_input; |
|---|
| 138 | + |
|---|
| 139 | + if (wblock == NULL || wdriver == NULL) |
|---|
| 140 | + return NULL; |
|---|
| 141 | + if (wdriver->id_table == NULL) |
|---|
| 142 | + return NULL; |
|---|
| 143 | + |
|---|
| 144 | + id = wdriver->id_table; |
|---|
| 145 | + while (*id->guid_string) { |
|---|
| 146 | + if (guid_parse(id->guid_string, &guid_input)) |
|---|
| 147 | + continue; |
|---|
| 148 | + if (!memcmp(wblock->gblock.guid, &guid_input, 16)) |
|---|
| 149 | + return id->context; |
|---|
| 150 | + id++; |
|---|
| 151 | + } |
|---|
| 152 | + return NULL; |
|---|
| 147 | 153 | } |
|---|
| 148 | 154 | |
|---|
| 149 | 155 | static int get_subobj_info(acpi_handle handle, const char *pathname, |
|---|
| .. | .. |
|---|
| 196 | 202 | /** |
|---|
| 197 | 203 | * set_required_buffer_size - Sets the buffer size needed for performing IOCTL |
|---|
| 198 | 204 | * @wdev: A wmi bus device from a driver |
|---|
| 199 | | - * @instance: Instance index |
|---|
| 205 | + * @length: Required buffer size |
|---|
| 200 | 206 | * |
|---|
| 201 | 207 | * Allocates memory needed for buffer, stores the buffer size in that memory |
|---|
| 202 | 208 | */ |
|---|
| .. | .. |
|---|
| 216 | 222 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 217 | 223 | * @instance: Instance index |
|---|
| 218 | 224 | * @method_id: Method ID to call |
|---|
| 219 | | - * &in: Buffer containing input for the method call |
|---|
| 220 | | - * &out: Empty buffer to return the method results |
|---|
| 225 | + * @in: Buffer containing input for the method call |
|---|
| 226 | + * @out: Empty buffer to return the method results |
|---|
| 221 | 227 | * |
|---|
| 222 | 228 | * Call an ACPI-WMI method |
|---|
| 223 | 229 | */ |
|---|
| .. | .. |
|---|
| 238 | 244 | * @wdev: A wmi bus device from a driver |
|---|
| 239 | 245 | * @instance: Instance index |
|---|
| 240 | 246 | * @method_id: Method ID to call |
|---|
| 241 | | - * &in: Buffer containing input for the method call |
|---|
| 242 | | - * &out: Empty buffer to return the method results |
|---|
| 247 | + * @in: Buffer containing input for the method call |
|---|
| 248 | + * @out: Empty buffer to return the method results |
|---|
| 243 | 249 | * |
|---|
| 244 | 250 | * Call an ACPI-WMI method |
|---|
| 245 | 251 | */ |
|---|
| .. | .. |
|---|
| 335 | 341 | * expensive, but have no corresponding WCxx method. So we |
|---|
| 336 | 342 | * should not fail if this happens. |
|---|
| 337 | 343 | */ |
|---|
| 338 | | - if (acpi_has_method(handle, wc_method)) |
|---|
| 339 | | - wc_status = acpi_execute_simple_method(handle, |
|---|
| 340 | | - wc_method, 1); |
|---|
| 344 | + wc_status = acpi_execute_simple_method(handle, wc_method, 1); |
|---|
| 341 | 345 | } |
|---|
| 342 | 346 | |
|---|
| 343 | 347 | strcpy(method, "WQ"); |
|---|
| .. | .. |
|---|
| 367 | 371 | * wmi_query_block - Return contents of a WMI block (deprecated) |
|---|
| 368 | 372 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 369 | 373 | * @instance: Instance index |
|---|
| 370 | | - * &out: Empty buffer to return the contents of the data block to |
|---|
| 374 | + * @out: Empty buffer to return the contents of the data block to |
|---|
| 371 | 375 | * |
|---|
| 372 | 376 | * Return the contents of an ACPI-WMI data block to a buffer |
|---|
| 373 | 377 | */ |
|---|
| .. | .. |
|---|
| 402 | 406 | * wmi_set_block - Write to a WMI block |
|---|
| 403 | 407 | * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 404 | 408 | * @instance: Instance index |
|---|
| 405 | | - * &in: Buffer containing new values for the data block |
|---|
| 409 | + * @in: Buffer containing new values for the data block |
|---|
| 406 | 410 | * |
|---|
| 407 | 411 | * Write the contents of the input buffer to an ACPI-WMI data block |
|---|
| 408 | 412 | */ |
|---|
| .. | .. |
|---|
| 513 | 517 | |
|---|
| 514 | 518 | /** |
|---|
| 515 | 519 | * wmi_install_notify_handler - Register handler for WMI events |
|---|
| 520 | + * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 516 | 521 | * @handler: Function to handle notifications |
|---|
| 517 | 522 | * @data: Data to be returned to handler when event is fired |
|---|
| 518 | 523 | * |
|---|
| .. | .. |
|---|
| 523 | 528 | { |
|---|
| 524 | 529 | struct wmi_block *block; |
|---|
| 525 | 530 | acpi_status status = AE_NOT_EXIST; |
|---|
| 526 | | - uuid_le guid_input; |
|---|
| 531 | + guid_t guid_input; |
|---|
| 527 | 532 | |
|---|
| 528 | 533 | if (!guid || !handler) |
|---|
| 529 | 534 | return AE_BAD_PARAMETER; |
|---|
| 530 | 535 | |
|---|
| 531 | | - if (uuid_le_to_bin(guid, &guid_input)) |
|---|
| 536 | + if (guid_parse(guid, &guid_input)) |
|---|
| 532 | 537 | return AE_BAD_PARAMETER; |
|---|
| 533 | 538 | |
|---|
| 534 | 539 | list_for_each_entry(block, &wmi_block_list, list) { |
|---|
| .. | .. |
|---|
| 555 | 560 | |
|---|
| 556 | 561 | /** |
|---|
| 557 | 562 | * wmi_uninstall_notify_handler - Unregister handler for WMI events |
|---|
| 563 | + * @guid: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 558 | 564 | * |
|---|
| 559 | 565 | * Unregister handler for events sent to the ACPI-WMI mapper device. |
|---|
| 560 | 566 | */ |
|---|
| .. | .. |
|---|
| 562 | 568 | { |
|---|
| 563 | 569 | struct wmi_block *block; |
|---|
| 564 | 570 | acpi_status status = AE_NOT_EXIST; |
|---|
| 565 | | - uuid_le guid_input; |
|---|
| 571 | + guid_t guid_input; |
|---|
| 566 | 572 | |
|---|
| 567 | 573 | if (!guid) |
|---|
| 568 | 574 | return AE_BAD_PARAMETER; |
|---|
| 569 | 575 | |
|---|
| 570 | | - if (uuid_le_to_bin(guid, &guid_input)) |
|---|
| 576 | + if (guid_parse(guid, &guid_input)) |
|---|
| 571 | 577 | return AE_BAD_PARAMETER; |
|---|
| 572 | 578 | |
|---|
| 573 | 579 | list_for_each_entry(block, &wmi_block_list, list) { |
|---|
| .. | .. |
|---|
| 641 | 647 | return find_guid(guid_string, NULL); |
|---|
| 642 | 648 | } |
|---|
| 643 | 649 | EXPORT_SYMBOL_GPL(wmi_has_guid); |
|---|
| 650 | + |
|---|
| 651 | +/** |
|---|
| 652 | + * wmi_get_acpi_device_uid() - Get _UID name of ACPI device that defines GUID |
|---|
| 653 | + * @guid_string: 36 char string of the form fa50ff2b-f2e8-45de-83fa-65417f2f49ba |
|---|
| 654 | + * |
|---|
| 655 | + * Find the _UID of ACPI device associated with this WMI GUID. |
|---|
| 656 | + * |
|---|
| 657 | + * Return: The ACPI _UID field value or NULL if the WMI GUID was not found |
|---|
| 658 | + */ |
|---|
| 659 | +char *wmi_get_acpi_device_uid(const char *guid_string) |
|---|
| 660 | +{ |
|---|
| 661 | + struct wmi_block *wblock = NULL; |
|---|
| 662 | + |
|---|
| 663 | + if (!find_guid(guid_string, &wblock)) |
|---|
| 664 | + return NULL; |
|---|
| 665 | + |
|---|
| 666 | + return acpi_device_uid(wblock->acpi_device); |
|---|
| 667 | +} |
|---|
| 668 | +EXPORT_SYMBOL_GPL(wmi_get_acpi_device_uid); |
|---|
| 644 | 669 | |
|---|
| 645 | 670 | static struct wmi_block *dev_to_wblock(struct device *dev) |
|---|
| 646 | 671 | { |
|---|
| .. | .. |
|---|
| 778 | 803 | if (id == NULL) |
|---|
| 779 | 804 | return 0; |
|---|
| 780 | 805 | |
|---|
| 781 | | - while (id->guid_string) { |
|---|
| 782 | | - uuid_le driver_guid; |
|---|
| 806 | + while (*id->guid_string) { |
|---|
| 807 | + guid_t driver_guid; |
|---|
| 783 | 808 | |
|---|
| 784 | | - if (WARN_ON(uuid_le_to_bin(id->guid_string, &driver_guid))) |
|---|
| 809 | + if (WARN_ON(guid_parse(id->guid_string, &driver_guid))) |
|---|
| 785 | 810 | continue; |
|---|
| 786 | 811 | if (!memcmp(&driver_guid, wblock->gblock.guid, 16)) |
|---|
| 787 | 812 | return 1; |
|---|
| .. | .. |
|---|
| 896 | 921 | .read = wmi_char_read, |
|---|
| 897 | 922 | .open = wmi_char_open, |
|---|
| 898 | 923 | .unlocked_ioctl = wmi_ioctl, |
|---|
| 899 | | - .compat_ioctl = wmi_ioctl, |
|---|
| 924 | + .compat_ioctl = compat_ptr_ioctl, |
|---|
| 900 | 925 | }; |
|---|
| 901 | 926 | |
|---|
| 902 | 927 | static int wmi_dev_probe(struct device *dev) |
|---|
| .. | .. |
|---|
| 911 | 936 | dev_warn(dev, "failed to enable device -- probing anyway\n"); |
|---|
| 912 | 937 | |
|---|
| 913 | 938 | if (wdriver->probe) { |
|---|
| 914 | | - ret = wdriver->probe(dev_to_wdev(dev)); |
|---|
| 939 | + ret = wdriver->probe(dev_to_wdev(dev), |
|---|
| 940 | + find_guid_context(wblock, wdriver)); |
|---|
| 915 | 941 | if (ret != 0) |
|---|
| 916 | 942 | goto probe_failure; |
|---|
| 917 | 943 | } |
|---|
| .. | .. |
|---|
| 997 | 1023 | .remove = wmi_dev_remove, |
|---|
| 998 | 1024 | }; |
|---|
| 999 | 1025 | |
|---|
| 1000 | | -static struct device_type wmi_type_event = { |
|---|
| 1026 | +static const struct device_type wmi_type_event = { |
|---|
| 1001 | 1027 | .name = "event", |
|---|
| 1002 | 1028 | .groups = wmi_event_groups, |
|---|
| 1003 | 1029 | .release = wmi_dev_release, |
|---|
| 1004 | 1030 | }; |
|---|
| 1005 | 1031 | |
|---|
| 1006 | | -static struct device_type wmi_type_method = { |
|---|
| 1032 | +static const struct device_type wmi_type_method = { |
|---|
| 1007 | 1033 | .name = "method", |
|---|
| 1008 | 1034 | .groups = wmi_method_groups, |
|---|
| 1009 | 1035 | .release = wmi_dev_release, |
|---|
| 1010 | 1036 | }; |
|---|
| 1011 | 1037 | |
|---|
| 1012 | | -static struct device_type wmi_type_data = { |
|---|
| 1038 | +static const struct device_type wmi_type_data = { |
|---|
| 1013 | 1039 | .name = "data", |
|---|
| 1014 | 1040 | .groups = wmi_data_groups, |
|---|
| 1015 | 1041 | .release = wmi_dev_release, |
|---|
| .. | .. |
|---|
| 1099 | 1125 | } |
|---|
| 1100 | 1126 | } |
|---|
| 1101 | 1127 | |
|---|
| 1102 | | -static bool guid_already_parsed(struct acpi_device *device, |
|---|
| 1103 | | - const u8 *guid) |
|---|
| 1128 | +static bool guid_already_parsed(struct acpi_device *device, const u8 *guid) |
|---|
| 1104 | 1129 | { |
|---|
| 1105 | 1130 | struct wmi_block *wblock; |
|---|
| 1106 | 1131 | |
|---|
| .. | .. |
|---|
| 1310 | 1335 | wblock->handler(event, wblock->handler_data); |
|---|
| 1311 | 1336 | } |
|---|
| 1312 | 1337 | |
|---|
| 1313 | | - if (debug_event) { |
|---|
| 1314 | | - pr_info("DEBUG Event GUID: %pUL\n", |
|---|
| 1315 | | - wblock->gblock.guid); |
|---|
| 1316 | | - } |
|---|
| 1338 | + if (debug_event) |
|---|
| 1339 | + pr_info("DEBUG Event GUID: %pUL\n", wblock->gblock.guid); |
|---|
| 1317 | 1340 | |
|---|
| 1318 | 1341 | acpi_bus_generate_netlink_event( |
|---|
| 1319 | 1342 | wblock->acpi_device->pnp.device_class, |
|---|