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

option_ms.c (3919B)


      1// SPDX-License-Identifier: GPL-2.0+
      2/*
      3 * Driver for Option High Speed Mobile Devices.
      4 *
      5 *   (c) 2008 Dan Williams <dcbw@redhat.com>
      6 *
      7 * Inspiration taken from sierra_ms.c by Kevin Lloyd <klloyd@sierrawireless.com>
      8 */
      9
     10#include <linux/usb.h>
     11#include <linux/slab.h>
     12#include <linux/module.h>
     13
     14#include "usb.h"
     15#include "transport.h"
     16#include "option_ms.h"
     17#include "debug.h"
     18
     19#define ZCD_FORCE_MODEM			0x01
     20#define ZCD_ALLOW_MS 			0x02
     21
     22static unsigned int option_zero_cd = ZCD_FORCE_MODEM;
     23module_param(option_zero_cd, uint, S_IRUGO | S_IWUSR);
     24MODULE_PARM_DESC(option_zero_cd, "ZeroCD mode (1=Force Modem (default),"
     25		 " 2=Allow CD-Rom");
     26
     27#define RESPONSE_LEN 1024
     28
     29static int option_rezero(struct us_data *us)
     30{
     31	static const unsigned char rezero_msg[] = {
     32	  0x55, 0x53, 0x42, 0x43, 0x78, 0x56, 0x34, 0x12,
     33	  0x01, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x01,
     34	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     35	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     36	};
     37	char *buffer;
     38	int result;
     39
     40	usb_stor_dbg(us, "Option MS: %s\n", "DEVICE MODE SWITCH");
     41
     42	buffer = kzalloc(RESPONSE_LEN, GFP_KERNEL);
     43	if (buffer == NULL)
     44		return USB_STOR_TRANSPORT_ERROR;
     45
     46	memcpy(buffer, rezero_msg, sizeof(rezero_msg));
     47	result = usb_stor_bulk_transfer_buf(us,
     48			us->send_bulk_pipe,
     49			buffer, sizeof(rezero_msg), NULL);
     50	if (result != USB_STOR_XFER_GOOD) {
     51		result = USB_STOR_XFER_ERROR;
     52		goto out;
     53	}
     54
     55	/*
     56	 * Some of the devices need to be asked for a response, but we don't
     57	 * care what that response is.
     58	 */
     59	usb_stor_bulk_transfer_buf(us,
     60			us->recv_bulk_pipe,
     61			buffer, RESPONSE_LEN, NULL);
     62
     63	/* Read the CSW */
     64	usb_stor_bulk_transfer_buf(us,
     65			us->recv_bulk_pipe,
     66			buffer, 13, NULL);
     67
     68	result = USB_STOR_XFER_GOOD;
     69
     70out:
     71	kfree(buffer);
     72	return result;
     73}
     74
     75static int option_inquiry(struct us_data *us)
     76{
     77	static const unsigned char inquiry_msg[] = {
     78	  0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
     79	  0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
     80	  0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
     81	  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     82	};
     83	char *buffer;
     84	int result;
     85
     86	usb_stor_dbg(us, "Option MS: %s\n", "device inquiry for vendor name");
     87
     88	buffer = kzalloc(0x24, GFP_KERNEL);
     89	if (buffer == NULL)
     90		return USB_STOR_TRANSPORT_ERROR;
     91
     92	memcpy(buffer, inquiry_msg, sizeof(inquiry_msg));
     93	result = usb_stor_bulk_transfer_buf(us,
     94			us->send_bulk_pipe,
     95			buffer, sizeof(inquiry_msg), NULL);
     96	if (result != USB_STOR_XFER_GOOD) {
     97		result = USB_STOR_XFER_ERROR;
     98		goto out;
     99	}
    100
    101	result = usb_stor_bulk_transfer_buf(us,
    102			us->recv_bulk_pipe,
    103			buffer, 0x24, NULL);
    104	if (result != USB_STOR_XFER_GOOD) {
    105		result = USB_STOR_XFER_ERROR;
    106		goto out;
    107	}
    108
    109	result = memcmp(buffer+8, "Option", 6);
    110
    111	if (result != 0)
    112		result = memcmp(buffer+8, "ZCOPTION", 8);
    113
    114	/* Read the CSW */
    115	usb_stor_bulk_transfer_buf(us,
    116			us->recv_bulk_pipe,
    117			buffer, 13, NULL);
    118
    119out:
    120	kfree(buffer);
    121	return result;
    122}
    123
    124
    125int option_ms_init(struct us_data *us)
    126{
    127	int result;
    128
    129	usb_stor_dbg(us, "Option MS: %s\n", "option_ms_init called");
    130
    131	/*
    132	 * Additional test for vendor information via INQUIRY,
    133	 * because some vendor/product IDs are ambiguous
    134	 */
    135	result = option_inquiry(us);
    136	if (result != 0) {
    137		usb_stor_dbg(us, "Option MS: %s\n",
    138			     "vendor is not Option or not determinable, no action taken");
    139		return 0;
    140	} else
    141		usb_stor_dbg(us, "Option MS: %s\n",
    142			     "this is a genuine Option device, proceeding");
    143
    144	/* Force Modem mode */
    145	if (option_zero_cd == ZCD_FORCE_MODEM) {
    146		usb_stor_dbg(us, "Option MS: %s\n", "Forcing Modem Mode");
    147		result = option_rezero(us);
    148		if (result != USB_STOR_XFER_GOOD)
    149			usb_stor_dbg(us, "Option MS: %s\n",
    150				     "Failed to switch to modem mode");
    151		return -EIO;
    152	} else if (option_zero_cd == ZCD_ALLOW_MS) {
    153		/* Allow Mass Storage mode (keep CD-Rom) */
    154		usb_stor_dbg(us, "Option MS: %s\n",
    155			     "Allowing Mass Storage Mode if device requests it");
    156	}
    157
    158	return 0;
    159}
    160