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

dell-wmi-privacy.c (10942B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Dell privacy notification driver
      4 *
      5 * Copyright (C) 2021 Dell Inc. All Rights Reserved.
      6 */
      7
      8#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
      9
     10#include <linux/acpi.h>
     11#include <linux/bitops.h>
     12#include <linux/input.h>
     13#include <linux/input/sparse-keymap.h>
     14#include <linux/list.h>
     15#include <linux/leds.h>
     16#include <linux/module.h>
     17#include <linux/wmi.h>
     18
     19#include "dell-wmi-privacy.h"
     20
     21#define DELL_PRIVACY_GUID "6932965F-1671-4CEB-B988-D3AB0A901919"
     22#define MICROPHONE_STATUS		BIT(0)
     23#define CAMERA_STATUS		        BIT(1)
     24#define DELL_PRIVACY_AUDIO_EVENT  0x1
     25#define DELL_PRIVACY_CAMERA_EVENT 0x2
     26#define led_to_priv(c)       container_of(c, struct privacy_wmi_data, cdev)
     27
     28/*
     29 * The wmi_list is used to store the privacy_priv struct with mutex protecting
     30 */
     31static LIST_HEAD(wmi_list);
     32static DEFINE_MUTEX(list_mutex);
     33
     34struct privacy_wmi_data {
     35	struct input_dev *input_dev;
     36	struct wmi_device *wdev;
     37	struct list_head list;
     38	struct led_classdev cdev;
     39	u32 features_present;
     40	u32 last_status;
     41};
     42
     43/* DELL Privacy Type */
     44enum dell_hardware_privacy_type {
     45	DELL_PRIVACY_TYPE_AUDIO = 0,
     46	DELL_PRIVACY_TYPE_CAMERA,
     47	DELL_PRIVACY_TYPE_SCREEN,
     48	DELL_PRIVACY_TYPE_MAX,
     49};
     50
     51static const char * const privacy_types[DELL_PRIVACY_TYPE_MAX] = {
     52	[DELL_PRIVACY_TYPE_AUDIO] = "Microphone",
     53	[DELL_PRIVACY_TYPE_CAMERA] = "Camera Shutter",
     54	[DELL_PRIVACY_TYPE_SCREEN] = "ePrivacy Screen",
     55};
     56
     57/*
     58 * Keymap for WMI privacy events of type 0x0012
     59 */
     60static const struct key_entry dell_wmi_keymap_type_0012[] = {
     61	/* privacy mic mute */
     62	{ KE_KEY, 0x0001, { KEY_MICMUTE } },
     63	/* privacy camera mute */
     64	{ KE_SW,  0x0002, { SW_CAMERA_LENS_COVER } },
     65	{ KE_END, 0},
     66};
     67
     68bool dell_privacy_has_mic_mute(void)
     69{
     70	struct privacy_wmi_data *priv;
     71
     72	mutex_lock(&list_mutex);
     73	priv = list_first_entry_or_null(&wmi_list,
     74			struct privacy_wmi_data,
     75			list);
     76	mutex_unlock(&list_mutex);
     77
     78	return priv && (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO));
     79}
     80EXPORT_SYMBOL_GPL(dell_privacy_has_mic_mute);
     81
     82/*
     83 * The flow of privacy event:
     84 * 1) User presses key. HW does stuff with this key (timeout is started)
     85 * 2) WMI event is emitted from BIOS
     86 * 3) WMI event is received by dell-privacy
     87 * 4) KEY_MICMUTE emitted from dell-privacy
     88 * 5) Userland picks up key and modifies kcontrol for SW mute
     89 * 6) Codec kernel driver catches and calls ledtrig_audio_set which will call
     90 *    led_set_brightness() on the LED registered by dell_privacy_leds_setup()
     91 * 7) dell-privacy notifies EC, the timeout is cancelled and the HW mute activates.
     92 *    If the EC is not notified then the HW mic mute will activate when the timeout
     93 *    triggers, just a bit later than with the active ack.
     94 */
     95bool dell_privacy_process_event(int type, int code, int status)
     96{
     97	struct privacy_wmi_data *priv;
     98	const struct key_entry *key;
     99	bool ret = false;
    100
    101	mutex_lock(&list_mutex);
    102	priv = list_first_entry_or_null(&wmi_list,
    103			struct privacy_wmi_data,
    104			list);
    105	if (!priv)
    106		goto error;
    107
    108	key = sparse_keymap_entry_from_scancode(priv->input_dev, (type << 16) | code);
    109	if (!key) {
    110		dev_warn(&priv->wdev->dev, "Unknown key with type 0x%04x and code 0x%04x pressed\n",
    111			type, code);
    112		goto error;
    113	}
    114	dev_dbg(&priv->wdev->dev, "Key with type 0x%04x and code 0x%04x pressed\n", type, code);
    115
    116	switch (code) {
    117	case DELL_PRIVACY_AUDIO_EVENT: /* Mic mute */
    118	case DELL_PRIVACY_CAMERA_EVENT: /* Camera mute */
    119		priv->last_status = status;
    120		sparse_keymap_report_entry(priv->input_dev, key, 1, true);
    121		ret = true;
    122		break;
    123	default:
    124		dev_dbg(&priv->wdev->dev, "unknown event type 0x%04x 0x%04x\n", type, code);
    125	}
    126
    127error:
    128	mutex_unlock(&list_mutex);
    129	return ret;
    130}
    131
    132static ssize_t dell_privacy_supported_type_show(struct device *dev,
    133					struct device_attribute *attr,
    134					char *buf)
    135{
    136	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
    137	enum dell_hardware_privacy_type type;
    138	u32 privacy_list;
    139	int len = 0;
    140
    141	privacy_list = priv->features_present;
    142	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
    143		if (privacy_list & BIT(type))
    144			len += sysfs_emit_at(buf, len, "[%s] [supported]\n", privacy_types[type]);
    145		else
    146			len += sysfs_emit_at(buf, len, "[%s] [unsupported]\n", privacy_types[type]);
    147	}
    148
    149	return len;
    150}
    151
    152static ssize_t dell_privacy_current_state_show(struct device *dev,
    153					struct device_attribute *attr,
    154					char *buf)
    155{
    156	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
    157	u32 privacy_supported = priv->features_present;
    158	enum dell_hardware_privacy_type type;
    159	u32 privacy_state = priv->last_status;
    160	int len = 0;
    161
    162	for (type = DELL_PRIVACY_TYPE_AUDIO; type < DELL_PRIVACY_TYPE_MAX; type++) {
    163		if (privacy_supported & BIT(type)) {
    164			if (privacy_state & BIT(type))
    165				len += sysfs_emit_at(buf, len, "[%s] [unmuted]\n", privacy_types[type]);
    166			else
    167				len += sysfs_emit_at(buf, len, "[%s] [muted]\n", privacy_types[type]);
    168		}
    169	}
    170
    171	return len;
    172}
    173
    174static DEVICE_ATTR_RO(dell_privacy_supported_type);
    175static DEVICE_ATTR_RO(dell_privacy_current_state);
    176
    177static struct attribute *privacy_attributes[] = {
    178	&dev_attr_dell_privacy_supported_type.attr,
    179	&dev_attr_dell_privacy_current_state.attr,
    180	NULL,
    181};
    182
    183static const struct attribute_group privacy_attribute_group = {
    184	.attrs = privacy_attributes
    185};
    186
    187/*
    188 * Describes the Device State class exposed by BIOS which can be consumed by
    189 * various applications interested in knowing the Privacy feature capabilities.
    190 * class DeviceState
    191 * {
    192 *  [key, read] string InstanceName;
    193 *  [read] boolean ReadOnly;
    194 *
    195 *  [WmiDataId(1), read] uint32 DevicesSupported;
    196 *   0 - None; 0x1 - Microphone; 0x2 - Camera; 0x4 - ePrivacy  Screen
    197 *
    198 *  [WmiDataId(2), read] uint32 CurrentState;
    199 *   0 - Off; 1 - On; Bit0 - Microphone; Bit1 - Camera; Bit2 - ePrivacyScreen
    200 * };
    201 */
    202static int get_current_status(struct wmi_device *wdev)
    203{
    204	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
    205	union acpi_object *obj_present;
    206	u32 *buffer;
    207	int ret = 0;
    208
    209	if (!priv) {
    210		dev_err(&wdev->dev, "dell privacy priv is NULL\n");
    211		return -EINVAL;
    212	}
    213	/* check privacy support features and device states */
    214	obj_present = wmidev_block_query(wdev, 0);
    215	if (!obj_present) {
    216		dev_err(&wdev->dev, "failed to read Binary MOF\n");
    217		return -EIO;
    218	}
    219
    220	if (obj_present->type != ACPI_TYPE_BUFFER) {
    221		dev_err(&wdev->dev, "Binary MOF is not a buffer!\n");
    222		ret = -EIO;
    223		goto obj_free;
    224	}
    225	/*  Although it's not technically a failure, this would lead to
    226	 *  unexpected behavior
    227	 */
    228	if (obj_present->buffer.length != 8) {
    229		dev_err(&wdev->dev, "Dell privacy buffer has unexpected length (%d)!\n",
    230				obj_present->buffer.length);
    231		ret = -EINVAL;
    232		goto obj_free;
    233	}
    234	buffer = (u32 *)obj_present->buffer.pointer;
    235	priv->features_present = buffer[0];
    236	priv->last_status = buffer[1];
    237
    238obj_free:
    239	kfree(obj_present);
    240	return ret;
    241}
    242
    243static int dell_privacy_micmute_led_set(struct led_classdev *led_cdev,
    244					enum led_brightness brightness)
    245{
    246	struct privacy_wmi_data *priv = led_to_priv(led_cdev);
    247	static char *acpi_method = (char *)"ECAK";
    248	acpi_status status;
    249	acpi_handle handle;
    250
    251	handle = ec_get_handle();
    252	if (!handle)
    253		return -EIO;
    254
    255	if (!acpi_has_method(handle, acpi_method))
    256		return -EIO;
    257
    258	status = acpi_evaluate_object(handle, acpi_method, NULL, NULL);
    259	if (ACPI_FAILURE(status)) {
    260		dev_err(&priv->wdev->dev, "Error setting privacy EC ack value: %s\n",
    261				acpi_format_exception(status));
    262		return -EIO;
    263	}
    264
    265	return 0;
    266}
    267
    268/*
    269 * Pressing the mute key activates a time delayed circuit to physically cut
    270 * off the mute. The LED is in the same circuit, so it reflects the true
    271 * state of the HW mute.  The reason for the EC "ack" is so that software
    272 * can first invoke a SW mute before the HW circuit is cut off.  Without SW
    273 * cutting this off first does not affect the time delayed muting or status
    274 * of the LED but there is a possibility of a "popping" noise.
    275 *
    276 * If the EC receives the SW ack, the circuit will be activated before the
    277 * delay completed.
    278 *
    279 * Exposing as an LED device allows the codec drivers notification path to
    280 * EC ACK to work
    281 */
    282static int dell_privacy_leds_setup(struct device *dev)
    283{
    284	struct privacy_wmi_data *priv = dev_get_drvdata(dev);
    285
    286	priv->cdev.name = "dell-privacy::micmute";
    287	priv->cdev.max_brightness = 1;
    288	priv->cdev.brightness_set_blocking = dell_privacy_micmute_led_set;
    289	priv->cdev.default_trigger = "audio-micmute";
    290	priv->cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
    291	return devm_led_classdev_register(dev, &priv->cdev);
    292}
    293
    294static int dell_privacy_wmi_probe(struct wmi_device *wdev, const void *context)
    295{
    296	struct privacy_wmi_data *priv;
    297	struct key_entry *keymap;
    298	int ret, i;
    299
    300	ret = wmi_has_guid(DELL_PRIVACY_GUID);
    301	if (!ret)
    302		pr_debug("Unable to detect available Dell privacy devices!\n");
    303
    304	priv = devm_kzalloc(&wdev->dev, sizeof(*priv), GFP_KERNEL);
    305	if (!priv)
    306		return -ENOMEM;
    307
    308	dev_set_drvdata(&wdev->dev, priv);
    309	priv->wdev = wdev;
    310	/* create evdev passing interface */
    311	priv->input_dev = devm_input_allocate_device(&wdev->dev);
    312	if (!priv->input_dev)
    313		return -ENOMEM;
    314
    315	/* remap the wmi keymap event to new keymap */
    316	keymap = kcalloc(ARRAY_SIZE(dell_wmi_keymap_type_0012),
    317			sizeof(struct key_entry), GFP_KERNEL);
    318	if (!keymap)
    319		return -ENOMEM;
    320
    321	/* remap the keymap code with Dell privacy key type 0x12 as prefix
    322	 * KEY_MICMUTE scancode will be reported as 0x120001
    323	 */
    324	for (i = 0; i < ARRAY_SIZE(dell_wmi_keymap_type_0012); i++) {
    325		keymap[i] = dell_wmi_keymap_type_0012[i];
    326		keymap[i].code |= (0x0012 << 16);
    327	}
    328	ret = sparse_keymap_setup(priv->input_dev, keymap, NULL);
    329	kfree(keymap);
    330	if (ret)
    331		return ret;
    332
    333	priv->input_dev->dev.parent = &wdev->dev;
    334	priv->input_dev->name = "Dell Privacy Driver";
    335	priv->input_dev->id.bustype = BUS_HOST;
    336
    337	ret = input_register_device(priv->input_dev);
    338	if (ret)
    339		return ret;
    340
    341	ret = get_current_status(priv->wdev);
    342	if (ret)
    343		return ret;
    344
    345	ret = devm_device_add_group(&wdev->dev, &privacy_attribute_group);
    346	if (ret)
    347		return ret;
    348
    349	if (priv->features_present & BIT(DELL_PRIVACY_TYPE_AUDIO)) {
    350		ret = dell_privacy_leds_setup(&priv->wdev->dev);
    351		if (ret)
    352			return ret;
    353	}
    354	mutex_lock(&list_mutex);
    355	list_add_tail(&priv->list, &wmi_list);
    356	mutex_unlock(&list_mutex);
    357	return 0;
    358}
    359
    360static void dell_privacy_wmi_remove(struct wmi_device *wdev)
    361{
    362	struct privacy_wmi_data *priv = dev_get_drvdata(&wdev->dev);
    363
    364	mutex_lock(&list_mutex);
    365	list_del(&priv->list);
    366	mutex_unlock(&list_mutex);
    367}
    368
    369static const struct wmi_device_id dell_wmi_privacy_wmi_id_table[] = {
    370	{ .guid_string = DELL_PRIVACY_GUID },
    371	{ },
    372};
    373
    374static struct wmi_driver dell_privacy_wmi_driver = {
    375	.driver = {
    376		.name = "dell-privacy",
    377	},
    378	.probe = dell_privacy_wmi_probe,
    379	.remove = dell_privacy_wmi_remove,
    380	.id_table = dell_wmi_privacy_wmi_id_table,
    381};
    382
    383int dell_privacy_register_driver(void)
    384{
    385	return wmi_driver_register(&dell_privacy_wmi_driver);
    386}
    387
    388void dell_privacy_unregister_driver(void)
    389{
    390	wmi_driver_unregister(&dell_privacy_wmi_driver);
    391}