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

rmi_f03.c (7979B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (C) 2015-2016 Red Hat
      4 * Copyright (C) 2015 Lyude Paul <thatslyude@gmail.com>
      5 */
      6
      7#include <linux/kernel.h>
      8#include <linux/slab.h>
      9#include <linux/serio.h>
     10#include <linux/notifier.h>
     11#include "rmi_driver.h"
     12
     13#define RMI_F03_RX_DATA_OFB		0x01
     14#define RMI_F03_OB_SIZE			2
     15
     16#define RMI_F03_OB_OFFSET		2
     17#define RMI_F03_OB_DATA_OFFSET		1
     18#define RMI_F03_OB_FLAG_TIMEOUT		BIT(6)
     19#define RMI_F03_OB_FLAG_PARITY		BIT(7)
     20
     21#define RMI_F03_DEVICE_COUNT		0x07
     22#define RMI_F03_BYTES_PER_DEVICE	0x07
     23#define RMI_F03_BYTES_PER_DEVICE_SHIFT	4
     24#define RMI_F03_QUEUE_LENGTH		0x0F
     25
     26#define PSMOUSE_OOB_EXTRA_BTNS		0x01
     27
     28struct f03_data {
     29	struct rmi_function *fn;
     30
     31	struct serio *serio;
     32	bool serio_registered;
     33
     34	unsigned int overwrite_buttons;
     35
     36	u8 device_count;
     37	u8 rx_queue_length;
     38};
     39
     40int rmi_f03_overwrite_button(struct rmi_function *fn, unsigned int button,
     41			     int value)
     42{
     43	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
     44	unsigned int bit;
     45
     46	if (button < BTN_LEFT || button > BTN_MIDDLE)
     47		return -EINVAL;
     48
     49	bit = BIT(button - BTN_LEFT);
     50
     51	if (value)
     52		f03->overwrite_buttons |= bit;
     53	else
     54		f03->overwrite_buttons &= ~bit;
     55
     56	return 0;
     57}
     58
     59void rmi_f03_commit_buttons(struct rmi_function *fn)
     60{
     61	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
     62	struct serio *serio = f03->serio;
     63
     64	serio_pause_rx(serio);
     65	if (serio->drv) {
     66		serio->drv->interrupt(serio, PSMOUSE_OOB_EXTRA_BTNS,
     67				      SERIO_OOB_DATA);
     68		serio->drv->interrupt(serio, f03->overwrite_buttons,
     69				      SERIO_OOB_DATA);
     70	}
     71	serio_continue_rx(serio);
     72}
     73
     74static int rmi_f03_pt_write(struct serio *id, unsigned char val)
     75{
     76	struct f03_data *f03 = id->port_data;
     77	int error;
     78
     79	rmi_dbg(RMI_DEBUG_FN, &f03->fn->dev,
     80		"%s: Wrote %.2hhx to PS/2 passthrough address",
     81		__func__, val);
     82
     83	error = rmi_write(f03->fn->rmi_dev, f03->fn->fd.data_base_addr, val);
     84	if (error) {
     85		dev_err(&f03->fn->dev,
     86			"%s: Failed to write to F03 TX register (%d).\n",
     87			__func__, error);
     88		return error;
     89	}
     90
     91	return 0;
     92}
     93
     94static int rmi_f03_initialize(struct f03_data *f03)
     95{
     96	struct rmi_function *fn = f03->fn;
     97	struct device *dev = &fn->dev;
     98	int error;
     99	u8 bytes_per_device;
    100	u8 query1;
    101	u8 query2[RMI_F03_DEVICE_COUNT * RMI_F03_BYTES_PER_DEVICE];
    102	size_t query2_len;
    103
    104	error = rmi_read(fn->rmi_dev, fn->fd.query_base_addr, &query1);
    105	if (error) {
    106		dev_err(dev, "Failed to read query register (%d).\n", error);
    107		return error;
    108	}
    109
    110	f03->device_count = query1 & RMI_F03_DEVICE_COUNT;
    111	bytes_per_device = (query1 >> RMI_F03_BYTES_PER_DEVICE_SHIFT) &
    112				RMI_F03_BYTES_PER_DEVICE;
    113
    114	query2_len = f03->device_count * bytes_per_device;
    115
    116	/*
    117	 * The first generation of image sensors don't have a second part to
    118	 * their f03 query, as such we have to set some of these values manually
    119	 */
    120	if (query2_len < 1) {
    121		f03->device_count = 1;
    122		f03->rx_queue_length = 7;
    123	} else {
    124		error = rmi_read_block(fn->rmi_dev, fn->fd.query_base_addr + 1,
    125				       query2, query2_len);
    126		if (error) {
    127			dev_err(dev,
    128				"Failed to read second set of query registers (%d).\n",
    129				error);
    130			return error;
    131		}
    132
    133		f03->rx_queue_length = query2[0] & RMI_F03_QUEUE_LENGTH;
    134	}
    135
    136	return 0;
    137}
    138
    139static int rmi_f03_pt_open(struct serio *serio)
    140{
    141	struct f03_data *f03 = serio->port_data;
    142	struct rmi_function *fn = f03->fn;
    143	const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
    144	const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
    145	u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
    146	int error;
    147
    148	/*
    149	 * Consume any pending data. Some devices like to spam with
    150	 * 0xaa 0x00 announcements which may confuse us as we try to
    151	 * probe the device.
    152	 */
    153	error = rmi_read_block(fn->rmi_dev, data_addr, &obs, ob_len);
    154	if (!error)
    155		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
    156			"%s: Consumed %*ph (%d) from PS2 guest\n",
    157			__func__, ob_len, obs, ob_len);
    158
    159	return fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
    160}
    161
    162static void rmi_f03_pt_close(struct serio *serio)
    163{
    164	struct f03_data *f03 = serio->port_data;
    165	struct rmi_function *fn = f03->fn;
    166
    167	fn->rmi_dev->driver->clear_irq_bits(fn->rmi_dev, fn->irq_mask);
    168}
    169
    170static int rmi_f03_register_pt(struct f03_data *f03)
    171{
    172	struct serio *serio;
    173
    174	serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
    175	if (!serio)
    176		return -ENOMEM;
    177
    178	serio->id.type = SERIO_PS_PSTHRU;
    179	serio->write = rmi_f03_pt_write;
    180	serio->open = rmi_f03_pt_open;
    181	serio->close = rmi_f03_pt_close;
    182	serio->port_data = f03;
    183
    184	strlcpy(serio->name, "RMI4 PS/2 pass-through", sizeof(serio->name));
    185	snprintf(serio->phys, sizeof(serio->phys), "%s/serio0",
    186		 dev_name(&f03->fn->dev));
    187	serio->dev.parent = &f03->fn->dev;
    188
    189	f03->serio = serio;
    190
    191	printk(KERN_INFO "serio: %s port at %s\n",
    192		serio->name, dev_name(&f03->fn->dev));
    193	serio_register_port(serio);
    194
    195	return 0;
    196}
    197
    198static int rmi_f03_probe(struct rmi_function *fn)
    199{
    200	struct device *dev = &fn->dev;
    201	struct f03_data *f03;
    202	int error;
    203
    204	f03 = devm_kzalloc(dev, sizeof(struct f03_data), GFP_KERNEL);
    205	if (!f03)
    206		return -ENOMEM;
    207
    208	f03->fn = fn;
    209
    210	error = rmi_f03_initialize(f03);
    211	if (error < 0)
    212		return error;
    213
    214	if (f03->device_count != 1)
    215		dev_warn(dev, "found %d devices on PS/2 passthrough",
    216			 f03->device_count);
    217
    218	dev_set_drvdata(dev, f03);
    219	return 0;
    220}
    221
    222static int rmi_f03_config(struct rmi_function *fn)
    223{
    224	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
    225	int error;
    226
    227	if (!f03->serio_registered) {
    228		error = rmi_f03_register_pt(f03);
    229		if (error)
    230			return error;
    231
    232		f03->serio_registered = true;
    233	} else {
    234		/*
    235		 * We must be re-configuring the sensor, just enable
    236		 * interrupts for this function.
    237		 */
    238		fn->rmi_dev->driver->set_irq_bits(fn->rmi_dev, fn->irq_mask);
    239	}
    240
    241	return 0;
    242}
    243
    244static irqreturn_t rmi_f03_attention(int irq, void *ctx)
    245{
    246	struct rmi_function *fn = ctx;
    247	struct rmi_device *rmi_dev = fn->rmi_dev;
    248	struct rmi_driver_data *drvdata = dev_get_drvdata(&rmi_dev->dev);
    249	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
    250	const u16 data_addr = fn->fd.data_base_addr + RMI_F03_OB_OFFSET;
    251	const u8 ob_len = f03->rx_queue_length * RMI_F03_OB_SIZE;
    252	u8 obs[RMI_F03_QUEUE_LENGTH * RMI_F03_OB_SIZE];
    253	u8 ob_status;
    254	u8 ob_data;
    255	unsigned int serio_flags;
    256	int i;
    257	int error;
    258
    259	if (drvdata->attn_data.data) {
    260		/* First grab the data passed by the transport device */
    261		if (drvdata->attn_data.size < ob_len) {
    262			dev_warn(&fn->dev, "F03 interrupted, but data is missing!\n");
    263			return IRQ_HANDLED;
    264		}
    265
    266		memcpy(obs, drvdata->attn_data.data, ob_len);
    267
    268		drvdata->attn_data.data += ob_len;
    269		drvdata->attn_data.size -= ob_len;
    270	} else {
    271		/* Grab all of the data registers, and check them for data */
    272		error = rmi_read_block(fn->rmi_dev, data_addr, &obs, ob_len);
    273		if (error) {
    274			dev_err(&fn->dev,
    275				"%s: Failed to read F03 output buffers: %d\n",
    276				__func__, error);
    277			serio_interrupt(f03->serio, 0, SERIO_TIMEOUT);
    278			return IRQ_RETVAL(error);
    279		}
    280	}
    281
    282	for (i = 0; i < ob_len; i += RMI_F03_OB_SIZE) {
    283		ob_status = obs[i];
    284		ob_data = obs[i + RMI_F03_OB_DATA_OFFSET];
    285		serio_flags = 0;
    286
    287		if (!(ob_status & RMI_F03_RX_DATA_OFB))
    288			continue;
    289
    290		if (ob_status & RMI_F03_OB_FLAG_TIMEOUT)
    291			serio_flags |= SERIO_TIMEOUT;
    292		if (ob_status & RMI_F03_OB_FLAG_PARITY)
    293			serio_flags |= SERIO_PARITY;
    294
    295		rmi_dbg(RMI_DEBUG_FN, &fn->dev,
    296			"%s: Received %.2hhx from PS2 guest T: %c P: %c\n",
    297			__func__, ob_data,
    298			serio_flags & SERIO_TIMEOUT ?  'Y' : 'N',
    299			serio_flags & SERIO_PARITY ? 'Y' : 'N');
    300
    301		serio_interrupt(f03->serio, ob_data, serio_flags);
    302	}
    303
    304	return IRQ_HANDLED;
    305}
    306
    307static void rmi_f03_remove(struct rmi_function *fn)
    308{
    309	struct f03_data *f03 = dev_get_drvdata(&fn->dev);
    310
    311	if (f03->serio_registered)
    312		serio_unregister_port(f03->serio);
    313}
    314
    315struct rmi_function_handler rmi_f03_handler = {
    316	.driver = {
    317		.name = "rmi4_f03",
    318	},
    319	.func = 0x03,
    320	.probe = rmi_f03_probe,
    321	.config = rmi_f03_config,
    322	.attention = rmi_f03_attention,
    323	.remove = rmi_f03_remove,
    324};
    325
    326MODULE_AUTHOR("Lyude Paul <thatslyude@gmail.com>");
    327MODULE_DESCRIPTION("RMI F03 module");
    328MODULE_LICENSE("GPL");