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

dbgp.c (8605B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * dbgp.c -- EHCI Debug Port device gadget
      4 *
      5 * Copyright (C) 2010 Stephane Duverger
      6 *
      7 * Released under the GPLv2.
      8 */
      9
     10/* verbose messages */
     11#include <linux/kernel.h>
     12#include <linux/device.h>
     13#include <linux/module.h>
     14#include <linux/usb/ch9.h>
     15#include <linux/usb/gadget.h>
     16
     17#include "u_serial.h"
     18
     19#define DRIVER_VENDOR_ID	0x0525 /* NetChip */
     20#define DRIVER_PRODUCT_ID	0xc0de /* undefined */
     21
     22#define USB_DEBUG_MAX_PACKET_SIZE     8
     23#define DBGP_REQ_EP0_LEN              128
     24#define DBGP_REQ_LEN                  512
     25
     26static struct dbgp {
     27	struct usb_gadget  *gadget;
     28	struct usb_request *req;
     29	struct usb_ep      *i_ep;
     30	struct usb_ep      *o_ep;
     31#ifdef CONFIG_USB_G_DBGP_SERIAL
     32	struct gserial     *serial;
     33#endif
     34} dbgp;
     35
     36static struct usb_device_descriptor device_desc = {
     37	.bLength = sizeof device_desc,
     38	.bDescriptorType = USB_DT_DEVICE,
     39	.bcdUSB = cpu_to_le16(0x0200),
     40	.bDeviceClass =	USB_CLASS_VENDOR_SPEC,
     41	.idVendor = cpu_to_le16(DRIVER_VENDOR_ID),
     42	.idProduct = cpu_to_le16(DRIVER_PRODUCT_ID),
     43	.bNumConfigurations = 1,
     44};
     45
     46static struct usb_debug_descriptor dbg_desc = {
     47	.bLength = sizeof dbg_desc,
     48	.bDescriptorType = USB_DT_DEBUG,
     49};
     50
     51static struct usb_endpoint_descriptor i_desc = {
     52	.bLength = USB_DT_ENDPOINT_SIZE,
     53	.bDescriptorType = USB_DT_ENDPOINT,
     54	.bmAttributes = USB_ENDPOINT_XFER_BULK,
     55	.bEndpointAddress = USB_DIR_IN,
     56};
     57
     58static struct usb_endpoint_descriptor o_desc = {
     59	.bLength = USB_DT_ENDPOINT_SIZE,
     60	.bDescriptorType = USB_DT_ENDPOINT,
     61	.bmAttributes = USB_ENDPOINT_XFER_BULK,
     62	.bEndpointAddress = USB_DIR_OUT,
     63};
     64
     65#ifdef CONFIG_USB_G_DBGP_PRINTK
     66static int dbgp_consume(char *buf, unsigned len)
     67{
     68	char c;
     69
     70	if (!len)
     71		return 0;
     72
     73	c = buf[len-1];
     74	if (c != 0)
     75		buf[len-1] = 0;
     76
     77	printk(KERN_NOTICE "%s%c", buf, c);
     78	return 0;
     79}
     80
     81static void __disable_ep(struct usb_ep *ep)
     82{
     83	usb_ep_disable(ep);
     84}
     85
     86static void dbgp_disable_ep(void)
     87{
     88	__disable_ep(dbgp.i_ep);
     89	__disable_ep(dbgp.o_ep);
     90}
     91
     92static void dbgp_complete(struct usb_ep *ep, struct usb_request *req)
     93{
     94	int stp;
     95	int err = 0;
     96	int status = req->status;
     97
     98	if (ep == dbgp.i_ep) {
     99		stp = 1;
    100		goto fail;
    101	}
    102
    103	if (status != 0) {
    104		stp = 2;
    105		goto release_req;
    106	}
    107
    108	dbgp_consume(req->buf, req->actual);
    109
    110	req->length = DBGP_REQ_LEN;
    111	err = usb_ep_queue(ep, req, GFP_ATOMIC);
    112	if (err < 0) {
    113		stp = 3;
    114		goto release_req;
    115	}
    116
    117	return;
    118
    119release_req:
    120	kfree(req->buf);
    121	usb_ep_free_request(dbgp.o_ep, req);
    122	dbgp_disable_ep();
    123fail:
    124	dev_dbg(&dbgp.gadget->dev,
    125		"complete: failure (%d:%d) ==> %d\n", stp, err, status);
    126}
    127
    128static int dbgp_enable_ep_req(struct usb_ep *ep)
    129{
    130	int err, stp;
    131	struct usb_request *req;
    132
    133	req = usb_ep_alloc_request(ep, GFP_KERNEL);
    134	if (!req) {
    135		err = -ENOMEM;
    136		stp = 1;
    137		goto fail_1;
    138	}
    139
    140	req->buf = kzalloc(DBGP_REQ_LEN, GFP_KERNEL);
    141	if (!req->buf) {
    142		err = -ENOMEM;
    143		stp = 2;
    144		goto fail_2;
    145	}
    146
    147	req->complete = dbgp_complete;
    148	req->length = DBGP_REQ_LEN;
    149	err = usb_ep_queue(ep, req, GFP_ATOMIC);
    150	if (err < 0) {
    151		stp = 3;
    152		goto fail_3;
    153	}
    154
    155	return 0;
    156
    157fail_3:
    158	kfree(req->buf);
    159fail_2:
    160	usb_ep_free_request(dbgp.o_ep, req);
    161fail_1:
    162	dev_dbg(&dbgp.gadget->dev,
    163		"enable ep req: failure (%d:%d)\n", stp, err);
    164	return err;
    165}
    166
    167static int __enable_ep(struct usb_ep *ep, struct usb_endpoint_descriptor *desc)
    168{
    169	int err;
    170	ep->desc = desc;
    171	err = usb_ep_enable(ep);
    172	return err;
    173}
    174
    175static int dbgp_enable_ep(void)
    176{
    177	int err, stp;
    178
    179	err = __enable_ep(dbgp.i_ep, &i_desc);
    180	if (err < 0) {
    181		stp = 1;
    182		goto fail_1;
    183	}
    184
    185	err = __enable_ep(dbgp.o_ep, &o_desc);
    186	if (err < 0) {
    187		stp = 2;
    188		goto fail_2;
    189	}
    190
    191	err = dbgp_enable_ep_req(dbgp.o_ep);
    192	if (err < 0) {
    193		stp = 3;
    194		goto fail_3;
    195	}
    196
    197	return 0;
    198
    199fail_3:
    200	__disable_ep(dbgp.o_ep);
    201fail_2:
    202	__disable_ep(dbgp.i_ep);
    203fail_1:
    204	dev_dbg(&dbgp.gadget->dev, "enable ep: failure (%d:%d)\n", stp, err);
    205	return err;
    206}
    207#endif
    208
    209static void dbgp_disconnect(struct usb_gadget *gadget)
    210{
    211#ifdef CONFIG_USB_G_DBGP_PRINTK
    212	dbgp_disable_ep();
    213#else
    214	gserial_disconnect(dbgp.serial);
    215#endif
    216}
    217
    218static void dbgp_unbind(struct usb_gadget *gadget)
    219{
    220#ifdef CONFIG_USB_G_DBGP_SERIAL
    221	kfree(dbgp.serial);
    222	dbgp.serial = NULL;
    223#endif
    224	if (dbgp.req) {
    225		kfree(dbgp.req->buf);
    226		usb_ep_free_request(gadget->ep0, dbgp.req);
    227		dbgp.req = NULL;
    228	}
    229}
    230
    231#ifdef CONFIG_USB_G_DBGP_SERIAL
    232static unsigned char tty_line;
    233#endif
    234
    235static int dbgp_configure_endpoints(struct usb_gadget *gadget)
    236{
    237	int stp;
    238
    239	usb_ep_autoconfig_reset(gadget);
    240
    241	dbgp.i_ep = usb_ep_autoconfig(gadget, &i_desc);
    242	if (!dbgp.i_ep) {
    243		stp = 1;
    244		goto fail_1;
    245	}
    246
    247	i_desc.wMaxPacketSize =
    248		cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
    249
    250	dbgp.o_ep = usb_ep_autoconfig(gadget, &o_desc);
    251	if (!dbgp.o_ep) {
    252		stp = 2;
    253		goto fail_1;
    254	}
    255
    256	o_desc.wMaxPacketSize =
    257		cpu_to_le16(USB_DEBUG_MAX_PACKET_SIZE);
    258
    259	dbg_desc.bDebugInEndpoint = i_desc.bEndpointAddress;
    260	dbg_desc.bDebugOutEndpoint = o_desc.bEndpointAddress;
    261
    262#ifdef CONFIG_USB_G_DBGP_SERIAL
    263	dbgp.serial->in = dbgp.i_ep;
    264	dbgp.serial->out = dbgp.o_ep;
    265
    266	dbgp.serial->in->desc = &i_desc;
    267	dbgp.serial->out->desc = &o_desc;
    268#endif
    269
    270	return 0;
    271
    272fail_1:
    273	dev_dbg(&dbgp.gadget->dev, "ep config: failure (%d)\n", stp);
    274	return -ENODEV;
    275}
    276
    277static int dbgp_bind(struct usb_gadget *gadget,
    278		struct usb_gadget_driver *driver)
    279{
    280	int err, stp;
    281
    282	dbgp.gadget = gadget;
    283
    284	dbgp.req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL);
    285	if (!dbgp.req) {
    286		err = -ENOMEM;
    287		stp = 1;
    288		goto fail;
    289	}
    290
    291	dbgp.req->buf = kmalloc(DBGP_REQ_EP0_LEN, GFP_KERNEL);
    292	if (!dbgp.req->buf) {
    293		err = -ENOMEM;
    294		stp = 2;
    295		goto fail;
    296	}
    297
    298	dbgp.req->length = DBGP_REQ_EP0_LEN;
    299
    300#ifdef CONFIG_USB_G_DBGP_SERIAL
    301	dbgp.serial = kzalloc(sizeof(struct gserial), GFP_KERNEL);
    302	if (!dbgp.serial) {
    303		stp = 3;
    304		err = -ENOMEM;
    305		goto fail;
    306	}
    307
    308	if (gserial_alloc_line(&tty_line)) {
    309		stp = 4;
    310		err = -ENODEV;
    311		goto fail;
    312	}
    313#endif
    314
    315	err = dbgp_configure_endpoints(gadget);
    316	if (err < 0) {
    317		stp = 5;
    318		goto fail;
    319	}
    320
    321	dev_dbg(&dbgp.gadget->dev, "bind: success\n");
    322	return 0;
    323
    324fail:
    325	dev_dbg(&gadget->dev, "bind: failure (%d:%d)\n", stp, err);
    326	dbgp_unbind(gadget);
    327	return err;
    328}
    329
    330static void dbgp_setup_complete(struct usb_ep *ep,
    331				struct usb_request *req)
    332{
    333	dev_dbg(&dbgp.gadget->dev, "setup complete: %d, %d/%d\n",
    334		req->status, req->actual, req->length);
    335}
    336
    337static int dbgp_setup(struct usb_gadget *gadget,
    338		      const struct usb_ctrlrequest *ctrl)
    339{
    340	struct usb_request *req = dbgp.req;
    341	u8 request = ctrl->bRequest;
    342	u16 value = le16_to_cpu(ctrl->wValue);
    343	u16 length = le16_to_cpu(ctrl->wLength);
    344	int err = -EOPNOTSUPP;
    345	void *data = NULL;
    346	u16 len = 0;
    347
    348	if (length > DBGP_REQ_LEN) {
    349		if (ctrl->bRequestType & USB_DIR_IN) {
    350			/* Cast away the const, we are going to overwrite on purpose. */
    351			__le16 *temp = (__le16 *)&ctrl->wLength;
    352
    353			*temp = cpu_to_le16(DBGP_REQ_LEN);
    354			length = DBGP_REQ_LEN;
    355		} else {
    356			return err;
    357		}
    358	}
    359
    360
    361	if (request == USB_REQ_GET_DESCRIPTOR) {
    362		switch (value>>8) {
    363		case USB_DT_DEVICE:
    364			dev_dbg(&dbgp.gadget->dev, "setup: desc device\n");
    365			len = sizeof device_desc;
    366			data = &device_desc;
    367			device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
    368			break;
    369		case USB_DT_DEBUG:
    370			dev_dbg(&dbgp.gadget->dev, "setup: desc debug\n");
    371			len = sizeof dbg_desc;
    372			data = &dbg_desc;
    373			break;
    374		default:
    375			goto fail;
    376		}
    377		err = 0;
    378	} else if (request == USB_REQ_SET_FEATURE &&
    379		   value == USB_DEVICE_DEBUG_MODE) {
    380		dev_dbg(&dbgp.gadget->dev, "setup: feat debug\n");
    381#ifdef CONFIG_USB_G_DBGP_PRINTK
    382		err = dbgp_enable_ep();
    383#else
    384		err = dbgp_configure_endpoints(gadget);
    385		if (err < 0) {
    386			goto fail;
    387		}
    388		err = gserial_connect(dbgp.serial, tty_line);
    389#endif
    390		if (err < 0)
    391			goto fail;
    392	} else
    393		goto fail;
    394
    395	req->length = min(length, len);
    396	req->zero = len < req->length;
    397	if (data && req->length)
    398		memcpy(req->buf, data, req->length);
    399
    400	req->complete = dbgp_setup_complete;
    401	return usb_ep_queue(gadget->ep0, req, GFP_ATOMIC);
    402
    403fail:
    404	dev_dbg(&dbgp.gadget->dev,
    405		"setup: failure req %x v %x\n", request, value);
    406	return err;
    407}
    408
    409static struct usb_gadget_driver dbgp_driver = {
    410	.function = "dbgp",
    411	.max_speed = USB_SPEED_HIGH,
    412	.bind = dbgp_bind,
    413	.unbind = dbgp_unbind,
    414	.setup = dbgp_setup,
    415	.reset = dbgp_disconnect,
    416	.disconnect = dbgp_disconnect,
    417	.driver	= {
    418		.owner = THIS_MODULE,
    419		.name = "dbgp"
    420	},
    421};
    422
    423static int __init dbgp_init(void)
    424{
    425	return usb_gadget_register_driver(&dbgp_driver);
    426}
    427
    428static void __exit dbgp_exit(void)
    429{
    430	usb_gadget_unregister_driver(&dbgp_driver);
    431#ifdef CONFIG_USB_G_DBGP_SERIAL
    432	gserial_free_line(tty_line);
    433#endif
    434}
    435
    436MODULE_AUTHOR("Stephane Duverger");
    437MODULE_LICENSE("GPL");
    438module_init(dbgp_init);
    439module_exit(dbgp_exit);