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

cros_ec_lpc.c (15933B)


      1// SPDX-License-Identifier: GPL-2.0
      2// LPC interface for ChromeOS Embedded Controller
      3//
      4// Copyright (C) 2012-2015 Google, Inc
      5//
      6// This driver uses the ChromeOS EC byte-level message-based protocol for
      7// communicating the keyboard state (which keys are pressed) from a keyboard EC
      8// to the AP over some bus (such as i2c, lpc, spi).  The EC does debouncing,
      9// but everything else (including deghosting) is done here.  The main
     10// motivation for this is to keep the EC firmware as simple as possible, since
     11// it cannot be easily upgraded and EC flash/IRAM space is relatively
     12// expensive.
     13
     14#include <linux/acpi.h>
     15#include <linux/dmi.h>
     16#include <linux/delay.h>
     17#include <linux/io.h>
     18#include <linux/interrupt.h>
     19#include <linux/module.h>
     20#include <linux/platform_data/cros_ec_commands.h>
     21#include <linux/platform_data/cros_ec_proto.h>
     22#include <linux/platform_device.h>
     23#include <linux/printk.h>
     24#include <linux/suspend.h>
     25
     26#include "cros_ec.h"
     27#include "cros_ec_lpc_mec.h"
     28
     29#define DRV_NAME "cros_ec_lpcs"
     30#define ACPI_DRV_NAME "GOOG0004"
     31
     32/* True if ACPI device is present */
     33static bool cros_ec_lpc_acpi_device_found;
     34
     35/**
     36 * struct lpc_driver_ops - LPC driver operations
     37 * @read: Copy length bytes from EC address offset into buffer dest. Returns
     38 *        the 8-bit checksum of all bytes read.
     39 * @write: Copy length bytes from buffer msg into EC address offset. Returns
     40 *         the 8-bit checksum of all bytes written.
     41 */
     42struct lpc_driver_ops {
     43	u8 (*read)(unsigned int offset, unsigned int length, u8 *dest);
     44	u8 (*write)(unsigned int offset, unsigned int length, const u8 *msg);
     45};
     46
     47static struct lpc_driver_ops cros_ec_lpc_ops = { };
     48
     49/*
     50 * A generic instance of the read function of struct lpc_driver_ops, used for
     51 * the LPC EC.
     52 */
     53static u8 cros_ec_lpc_read_bytes(unsigned int offset, unsigned int length,
     54				 u8 *dest)
     55{
     56	int sum = 0;
     57	int i;
     58
     59	for (i = 0; i < length; ++i) {
     60		dest[i] = inb(offset + i);
     61		sum += dest[i];
     62	}
     63
     64	/* Return checksum of all bytes read */
     65	return sum;
     66}
     67
     68/*
     69 * A generic instance of the write function of struct lpc_driver_ops, used for
     70 * the LPC EC.
     71 */
     72static u8 cros_ec_lpc_write_bytes(unsigned int offset, unsigned int length,
     73				  const u8 *msg)
     74{
     75	int sum = 0;
     76	int i;
     77
     78	for (i = 0; i < length; ++i) {
     79		outb(msg[i], offset + i);
     80		sum += msg[i];
     81	}
     82
     83	/* Return checksum of all bytes written */
     84	return sum;
     85}
     86
     87/*
     88 * An instance of the read function of struct lpc_driver_ops, used for the
     89 * MEC variant of LPC EC.
     90 */
     91static u8 cros_ec_lpc_mec_read_bytes(unsigned int offset, unsigned int length,
     92				     u8 *dest)
     93{
     94	int in_range = cros_ec_lpc_mec_in_range(offset, length);
     95
     96	if (in_range < 0)
     97		return 0;
     98
     99	return in_range ?
    100		cros_ec_lpc_io_bytes_mec(MEC_IO_READ,
    101					 offset - EC_HOST_CMD_REGION0,
    102					 length, dest) :
    103		cros_ec_lpc_read_bytes(offset, length, dest);
    104}
    105
    106/*
    107 * An instance of the write function of struct lpc_driver_ops, used for the
    108 * MEC variant of LPC EC.
    109 */
    110static u8 cros_ec_lpc_mec_write_bytes(unsigned int offset, unsigned int length,
    111				      const u8 *msg)
    112{
    113	int in_range = cros_ec_lpc_mec_in_range(offset, length);
    114
    115	if (in_range < 0)
    116		return 0;
    117
    118	return in_range ?
    119		cros_ec_lpc_io_bytes_mec(MEC_IO_WRITE,
    120					 offset - EC_HOST_CMD_REGION0,
    121					 length, (u8 *)msg) :
    122		cros_ec_lpc_write_bytes(offset, length, msg);
    123}
    124
    125static int ec_response_timed_out(void)
    126{
    127	unsigned long one_second = jiffies + HZ;
    128	u8 data;
    129
    130	usleep_range(200, 300);
    131	do {
    132		if (!(cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_CMD, 1, &data) &
    133		    EC_LPC_STATUS_BUSY_MASK))
    134			return 0;
    135		usleep_range(100, 200);
    136	} while (time_before(jiffies, one_second));
    137
    138	return 1;
    139}
    140
    141static int cros_ec_pkt_xfer_lpc(struct cros_ec_device *ec,
    142				struct cros_ec_command *msg)
    143{
    144	struct ec_host_response response;
    145	u8 sum;
    146	int ret = 0;
    147	u8 *dout;
    148
    149	ret = cros_ec_prepare_tx(ec, msg);
    150	if (ret < 0)
    151		goto done;
    152
    153	/* Write buffer */
    154	cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PACKET, ret, ec->dout);
    155
    156	/* Here we go */
    157	sum = EC_COMMAND_PROTOCOL_3;
    158	cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
    159
    160	if (ec_response_timed_out()) {
    161		dev_warn(ec->dev, "EC response timed out\n");
    162		ret = -EIO;
    163		goto done;
    164	}
    165
    166	/* Check result */
    167	msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
    168	ret = cros_ec_check_result(ec, msg);
    169	if (ret)
    170		goto done;
    171
    172	/* Read back response */
    173	dout = (u8 *)&response;
    174	sum = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET, sizeof(response),
    175				   dout);
    176
    177	msg->result = response.result;
    178
    179	if (response.data_len > msg->insize) {
    180		dev_err(ec->dev,
    181			"packet too long (%d bytes, expected %d)",
    182			response.data_len, msg->insize);
    183		ret = -EMSGSIZE;
    184		goto done;
    185	}
    186
    187	/* Read response and process checksum */
    188	sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PACKET +
    189				    sizeof(response), response.data_len,
    190				    msg->data);
    191
    192	if (sum) {
    193		dev_err(ec->dev,
    194			"bad packet checksum %02x\n",
    195			response.checksum);
    196		ret = -EBADMSG;
    197		goto done;
    198	}
    199
    200	/* Return actual amount of data received */
    201	ret = response.data_len;
    202done:
    203	return ret;
    204}
    205
    206static int cros_ec_cmd_xfer_lpc(struct cros_ec_device *ec,
    207				struct cros_ec_command *msg)
    208{
    209	struct ec_lpc_host_args args;
    210	u8 sum;
    211	int ret = 0;
    212
    213	if (msg->outsize > EC_PROTO2_MAX_PARAM_SIZE ||
    214	    msg->insize > EC_PROTO2_MAX_PARAM_SIZE) {
    215		dev_err(ec->dev,
    216			"invalid buffer sizes (out %d, in %d)\n",
    217			msg->outsize, msg->insize);
    218		return -EINVAL;
    219	}
    220
    221	/* Now actually send the command to the EC and get the result */
    222	args.flags = EC_HOST_ARGS_FLAG_FROM_HOST;
    223	args.command_version = msg->version;
    224	args.data_size = msg->outsize;
    225
    226	/* Initialize checksum */
    227	sum = msg->command + args.flags + args.command_version + args.data_size;
    228
    229	/* Copy data and update checksum */
    230	sum += cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_PARAM, msg->outsize,
    231				     msg->data);
    232
    233	/* Finalize checksum and write args */
    234	args.checksum = sum;
    235	cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_ARGS, sizeof(args),
    236			      (u8 *)&args);
    237
    238	/* Here we go */
    239	sum = msg->command;
    240	cros_ec_lpc_ops.write(EC_LPC_ADDR_HOST_CMD, 1, &sum);
    241
    242	if (ec_response_timed_out()) {
    243		dev_warn(ec->dev, "EC response timed out\n");
    244		ret = -EIO;
    245		goto done;
    246	}
    247
    248	/* Check result */
    249	msg->result = cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_DATA, 1, &sum);
    250	ret = cros_ec_check_result(ec, msg);
    251	if (ret)
    252		goto done;
    253
    254	/* Read back args */
    255	cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_ARGS, sizeof(args), (u8 *)&args);
    256
    257	if (args.data_size > msg->insize) {
    258		dev_err(ec->dev,
    259			"packet too long (%d bytes, expected %d)",
    260			args.data_size, msg->insize);
    261		ret = -ENOSPC;
    262		goto done;
    263	}
    264
    265	/* Start calculating response checksum */
    266	sum = msg->command + args.flags + args.command_version + args.data_size;
    267
    268	/* Read response and update checksum */
    269	sum += cros_ec_lpc_ops.read(EC_LPC_ADDR_HOST_PARAM, args.data_size,
    270				    msg->data);
    271
    272	/* Verify checksum */
    273	if (args.checksum != sum) {
    274		dev_err(ec->dev,
    275			"bad packet checksum, expected %02x, got %02x\n",
    276			args.checksum, sum);
    277		ret = -EBADMSG;
    278		goto done;
    279	}
    280
    281	/* Return actual amount of data received */
    282	ret = args.data_size;
    283done:
    284	return ret;
    285}
    286
    287/* Returns num bytes read, or negative on error. Doesn't need locking. */
    288static int cros_ec_lpc_readmem(struct cros_ec_device *ec, unsigned int offset,
    289			       unsigned int bytes, void *dest)
    290{
    291	int i = offset;
    292	char *s = dest;
    293	int cnt = 0;
    294
    295	if (offset >= EC_MEMMAP_SIZE - bytes)
    296		return -EINVAL;
    297
    298	/* fixed length */
    299	if (bytes) {
    300		cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + offset, bytes, s);
    301		return bytes;
    302	}
    303
    304	/* string */
    305	for (; i < EC_MEMMAP_SIZE; i++, s++) {
    306		cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + i, 1, s);
    307		cnt++;
    308		if (!*s)
    309			break;
    310	}
    311
    312	return cnt;
    313}
    314
    315static void cros_ec_lpc_acpi_notify(acpi_handle device, u32 value, void *data)
    316{
    317	struct cros_ec_device *ec_dev = data;
    318	bool ec_has_more_events;
    319	int ret;
    320
    321	ec_dev->last_event_time = cros_ec_get_time_ns();
    322
    323	if (ec_dev->mkbp_event_supported)
    324		do {
    325			ret = cros_ec_get_next_event(ec_dev, NULL,
    326						     &ec_has_more_events);
    327			if (ret > 0)
    328				blocking_notifier_call_chain(
    329						&ec_dev->event_notifier, 0,
    330						ec_dev);
    331		} while (ec_has_more_events);
    332
    333	if (value == ACPI_NOTIFY_DEVICE_WAKE)
    334		pm_system_wakeup();
    335}
    336
    337static int cros_ec_lpc_probe(struct platform_device *pdev)
    338{
    339	struct device *dev = &pdev->dev;
    340	struct acpi_device *adev;
    341	acpi_status status;
    342	struct cros_ec_device *ec_dev;
    343	u8 buf[2];
    344	int irq, ret;
    345
    346	/*
    347	 * The Framework Laptop (and possibly other non-ChromeOS devices)
    348	 * only exposes the eight I/O ports that are required for the Microchip EC.
    349	 * Requesting a larger reservation will fail.
    350	 */
    351	if (!devm_request_region(dev, EC_HOST_CMD_REGION0,
    352				 EC_HOST_CMD_MEC_REGION_SIZE, dev_name(dev))) {
    353		dev_err(dev, "couldn't reserve MEC region\n");
    354		return -EBUSY;
    355	}
    356
    357	/*
    358	 * Read the mapped ID twice, the first one is assuming the
    359	 * EC is a Microchip Embedded Controller (MEC) variant, if the
    360	 * protocol fails, fallback to the non MEC variant and try to
    361	 * read again the ID.
    362	 */
    363	cros_ec_lpc_ops.read = cros_ec_lpc_mec_read_bytes;
    364	cros_ec_lpc_ops.write = cros_ec_lpc_mec_write_bytes;
    365	cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2, buf);
    366	if (buf[0] != 'E' || buf[1] != 'C') {
    367		if (!devm_request_region(dev, EC_LPC_ADDR_MEMMAP, EC_MEMMAP_SIZE,
    368					 dev_name(dev))) {
    369			dev_err(dev, "couldn't reserve memmap region\n");
    370			return -EBUSY;
    371		}
    372
    373		/* Re-assign read/write operations for the non MEC variant */
    374		cros_ec_lpc_ops.read = cros_ec_lpc_read_bytes;
    375		cros_ec_lpc_ops.write = cros_ec_lpc_write_bytes;
    376		cros_ec_lpc_ops.read(EC_LPC_ADDR_MEMMAP + EC_MEMMAP_ID, 2,
    377				     buf);
    378		if (buf[0] != 'E' || buf[1] != 'C') {
    379			dev_err(dev, "EC ID not detected\n");
    380			return -ENODEV;
    381		}
    382
    383		/* Reserve the remaining I/O ports required by the non-MEC protocol. */
    384		if (!devm_request_region(dev, EC_HOST_CMD_REGION0 + EC_HOST_CMD_MEC_REGION_SIZE,
    385					 EC_HOST_CMD_REGION_SIZE - EC_HOST_CMD_MEC_REGION_SIZE,
    386					 dev_name(dev))) {
    387			dev_err(dev, "couldn't reserve remainder of region0\n");
    388			return -EBUSY;
    389		}
    390		if (!devm_request_region(dev, EC_HOST_CMD_REGION1,
    391					 EC_HOST_CMD_REGION_SIZE, dev_name(dev))) {
    392			dev_err(dev, "couldn't reserve region1\n");
    393			return -EBUSY;
    394		}
    395	}
    396
    397	ec_dev = devm_kzalloc(dev, sizeof(*ec_dev), GFP_KERNEL);
    398	if (!ec_dev)
    399		return -ENOMEM;
    400
    401	platform_set_drvdata(pdev, ec_dev);
    402	ec_dev->dev = dev;
    403	ec_dev->phys_name = dev_name(dev);
    404	ec_dev->cmd_xfer = cros_ec_cmd_xfer_lpc;
    405	ec_dev->pkt_xfer = cros_ec_pkt_xfer_lpc;
    406	ec_dev->cmd_readmem = cros_ec_lpc_readmem;
    407	ec_dev->din_size = sizeof(struct ec_host_response) +
    408			   sizeof(struct ec_response_get_protocol_info);
    409	ec_dev->dout_size = sizeof(struct ec_host_request);
    410
    411	/*
    412	 * Some boards do not have an IRQ allotted for cros_ec_lpc,
    413	 * which makes ENXIO an expected (and safe) scenario.
    414	 */
    415	irq = platform_get_irq_optional(pdev, 0);
    416	if (irq > 0)
    417		ec_dev->irq = irq;
    418	else if (irq != -ENXIO) {
    419		dev_err(dev, "couldn't retrieve IRQ number (%d)\n", irq);
    420		return irq;
    421	}
    422
    423	ret = cros_ec_register(ec_dev);
    424	if (ret) {
    425		dev_err(dev, "couldn't register ec_dev (%d)\n", ret);
    426		return ret;
    427	}
    428
    429	/*
    430	 * Connect a notify handler to process MKBP messages if we have a
    431	 * companion ACPI device.
    432	 */
    433	adev = ACPI_COMPANION(dev);
    434	if (adev) {
    435		status = acpi_install_notify_handler(adev->handle,
    436						     ACPI_ALL_NOTIFY,
    437						     cros_ec_lpc_acpi_notify,
    438						     ec_dev);
    439		if (ACPI_FAILURE(status))
    440			dev_warn(dev, "Failed to register notifier %08x\n",
    441				 status);
    442	}
    443
    444	return 0;
    445}
    446
    447static int cros_ec_lpc_remove(struct platform_device *pdev)
    448{
    449	struct cros_ec_device *ec_dev = platform_get_drvdata(pdev);
    450	struct acpi_device *adev;
    451
    452	adev = ACPI_COMPANION(&pdev->dev);
    453	if (adev)
    454		acpi_remove_notify_handler(adev->handle, ACPI_ALL_NOTIFY,
    455					   cros_ec_lpc_acpi_notify);
    456
    457	cros_ec_unregister(ec_dev);
    458
    459	return 0;
    460}
    461
    462static const struct acpi_device_id cros_ec_lpc_acpi_device_ids[] = {
    463	{ ACPI_DRV_NAME, 0 },
    464	{ }
    465};
    466MODULE_DEVICE_TABLE(acpi, cros_ec_lpc_acpi_device_ids);
    467
    468static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
    469	{
    470		/*
    471		 * Today all Chromebooks/boxes ship with Google_* as version and
    472		 * coreboot as bios vendor. No other systems with this
    473		 * combination are known to date.
    474		 */
    475		.matches = {
    476			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
    477			DMI_MATCH(DMI_BIOS_VERSION, "Google_"),
    478		},
    479	},
    480	{
    481		/*
    482		 * If the box is running custom coreboot firmware then the
    483		 * DMI BIOS version string will not be matched by "Google_",
    484		 * but the system vendor string will still be matched by
    485		 * "GOOGLE".
    486		 */
    487		.matches = {
    488			DMI_MATCH(DMI_BIOS_VENDOR, "coreboot"),
    489			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
    490		},
    491	},
    492	{
    493		/* x86-link, the Chromebook Pixel. */
    494		.matches = {
    495			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
    496			DMI_MATCH(DMI_PRODUCT_NAME, "Link"),
    497		},
    498	},
    499	{
    500		/* x86-samus, the Chromebook Pixel 2. */
    501		.matches = {
    502			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
    503			DMI_MATCH(DMI_PRODUCT_NAME, "Samus"),
    504		},
    505	},
    506	{
    507		/* x86-peppy, the Acer C720 Chromebook. */
    508		.matches = {
    509			DMI_MATCH(DMI_SYS_VENDOR, "Acer"),
    510			DMI_MATCH(DMI_PRODUCT_NAME, "Peppy"),
    511		},
    512	},
    513	{
    514		/* x86-glimmer, the Lenovo Thinkpad Yoga 11e. */
    515		.matches = {
    516			DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
    517			DMI_MATCH(DMI_PRODUCT_NAME, "Glimmer"),
    518		},
    519	},
    520	/* A small number of non-Chromebook/box machines also use the ChromeOS EC */
    521	{
    522		/* the Framework Laptop */
    523		.matches = {
    524			DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
    525			DMI_MATCH(DMI_PRODUCT_NAME, "Laptop"),
    526		},
    527	},
    528	{ /* sentinel */ }
    529};
    530MODULE_DEVICE_TABLE(dmi, cros_ec_lpc_dmi_table);
    531
    532#ifdef CONFIG_PM_SLEEP
    533static int cros_ec_lpc_suspend(struct device *dev)
    534{
    535	struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
    536
    537	return cros_ec_suspend(ec_dev);
    538}
    539
    540static int cros_ec_lpc_resume(struct device *dev)
    541{
    542	struct cros_ec_device *ec_dev = dev_get_drvdata(dev);
    543
    544	return cros_ec_resume(ec_dev);
    545}
    546#endif
    547
    548static const struct dev_pm_ops cros_ec_lpc_pm_ops = {
    549	SET_LATE_SYSTEM_SLEEP_PM_OPS(cros_ec_lpc_suspend, cros_ec_lpc_resume)
    550};
    551
    552static struct platform_driver cros_ec_lpc_driver = {
    553	.driver = {
    554		.name = DRV_NAME,
    555		.acpi_match_table = cros_ec_lpc_acpi_device_ids,
    556		.pm = &cros_ec_lpc_pm_ops,
    557	},
    558	.probe = cros_ec_lpc_probe,
    559	.remove = cros_ec_lpc_remove,
    560};
    561
    562static struct platform_device cros_ec_lpc_device = {
    563	.name = DRV_NAME
    564};
    565
    566static acpi_status cros_ec_lpc_parse_device(acpi_handle handle, u32 level,
    567					    void *context, void **retval)
    568{
    569	*(bool *)context = true;
    570	return AE_CTRL_TERMINATE;
    571}
    572
    573static int __init cros_ec_lpc_init(void)
    574{
    575	int ret;
    576	acpi_status status;
    577
    578	status = acpi_get_devices(ACPI_DRV_NAME, cros_ec_lpc_parse_device,
    579				  &cros_ec_lpc_acpi_device_found, NULL);
    580	if (ACPI_FAILURE(status))
    581		pr_warn(DRV_NAME ": Looking for %s failed\n", ACPI_DRV_NAME);
    582
    583	if (!cros_ec_lpc_acpi_device_found &&
    584	    !dmi_check_system(cros_ec_lpc_dmi_table)) {
    585		pr_err(DRV_NAME ": unsupported system.\n");
    586		return -ENODEV;
    587	}
    588
    589	cros_ec_lpc_mec_init(EC_HOST_CMD_REGION0,
    590			     EC_LPC_ADDR_MEMMAP + EC_MEMMAP_SIZE);
    591
    592	/* Register the driver */
    593	ret = platform_driver_register(&cros_ec_lpc_driver);
    594	if (ret) {
    595		pr_err(DRV_NAME ": can't register driver: %d\n", ret);
    596		cros_ec_lpc_mec_destroy();
    597		return ret;
    598	}
    599
    600	if (!cros_ec_lpc_acpi_device_found) {
    601		/* Register the device, and it'll get hooked up automatically */
    602		ret = platform_device_register(&cros_ec_lpc_device);
    603		if (ret) {
    604			pr_err(DRV_NAME ": can't register device: %d\n", ret);
    605			platform_driver_unregister(&cros_ec_lpc_driver);
    606			cros_ec_lpc_mec_destroy();
    607		}
    608	}
    609
    610	return ret;
    611}
    612
    613static void __exit cros_ec_lpc_exit(void)
    614{
    615	if (!cros_ec_lpc_acpi_device_found)
    616		platform_device_unregister(&cros_ec_lpc_device);
    617	platform_driver_unregister(&cros_ec_lpc_driver);
    618	cros_ec_lpc_mec_destroy();
    619}
    620
    621module_init(cros_ec_lpc_init);
    622module_exit(cros_ec_lpc_exit);
    623
    624MODULE_LICENSE("GPL");
    625MODULE_DESCRIPTION("ChromeOS EC LPC driver");