uboot/drivers/usb/emul/sandbox_flash.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2015 Google, Inc
   3 * Written by Simon Glass <sjg@chromium.org>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <dm.h>
  10#include <os.h>
  11#include <scsi.h>
  12#include <usb.h>
  13
  14DECLARE_GLOBAL_DATA_PTR;
  15
  16/*
  17 * This driver emulates a flash stick using the UFI command specification and
  18 * the BBB (bulk/bulk/bulk) protocol. It supports only a single logical unit
  19 * number (LUN 0).
  20 */
  21
  22enum {
  23        SANDBOX_FLASH_EP_OUT            = 1,    /* endpoints */
  24        SANDBOX_FLASH_EP_IN             = 2,
  25        SANDBOX_FLASH_BLOCK_LEN         = 512,
  26};
  27
  28enum cmd_phase {
  29        PHASE_START,
  30        PHASE_DATA,
  31        PHASE_STATUS,
  32};
  33
  34/**
  35 * struct sandbox_flash_priv - private state for this driver
  36 *
  37 * @error:      true if there is an error condition
  38 * @alloc_len:  Allocation length from the last incoming command
  39 * @transfer_len: Transfer length from CBW header
  40 * @read_len:   Number of blocks of data left in the current read command
  41 * @tag:        Tag value from last command
  42 * @fd:         File descriptor of backing file
  43 * @file_size:  Size of file in bytes
  44 * @status_buff:        Data buffer for outgoing status
  45 * @buff_used:  Number of bytes ready to transfer back to host
  46 * @buff:       Data buffer for outgoing data
  47 */
  48struct sandbox_flash_priv {
  49        bool error;
  50        int alloc_len;
  51        int transfer_len;
  52        int read_len;
  53        enum cmd_phase phase;
  54        u32 tag;
  55        int fd;
  56        loff_t file_size;
  57        struct umass_bbb_csw status;
  58        int buff_used;
  59        u8 buff[512];
  60};
  61
  62struct sandbox_flash_plat {
  63        const char *pathname;
  64};
  65
  66struct scsi_inquiry_resp {
  67        u8 type;
  68        u8 flags;
  69        u8 version;
  70        u8 data_format;
  71        u8 additional_len;
  72        u8 spare[3];
  73        char vendor[8];
  74        char product[16];
  75        char revision[4];
  76};
  77
  78struct scsi_read_capacity_resp {
  79        u32 last_block_addr;
  80        u32 block_len;
  81};
  82
  83struct __packed scsi_read10_req {
  84        u8 cmd;
  85        u8 lun_flags;
  86        u32 lba;
  87        u8 spare;
  88        u16 transfer_len;
  89        u8 spare2[3];
  90};
  91
  92enum {
  93        STRINGID_MANUFACTURER = 1,
  94        STRINGID_PRODUCT,
  95        STRINGID_SERIAL,
  96
  97        STRINGID_COUNT,
  98};
  99
 100static struct usb_string flash_strings[] = {
 101        {STRINGID_MANUFACTURER, "sandbox"},
 102        {STRINGID_PRODUCT,      "flash"},
 103        {STRINGID_SERIAL,       "2345"},
 104        {},
 105};
 106
 107static struct usb_device_descriptor flash_device_desc = {
 108        .bLength =              sizeof(flash_device_desc),
 109        .bDescriptorType =      USB_DT_DEVICE,
 110
 111        .bcdUSB =               __constant_cpu_to_le16(0x0200),
 112
 113        .bDeviceClass =         0,
 114        .bDeviceSubClass =      0,
 115        .bDeviceProtocol =      0,
 116
 117        .idVendor =             __constant_cpu_to_le16(0x1234),
 118        .idProduct =            __constant_cpu_to_le16(0x5678),
 119        .iManufacturer =        STRINGID_MANUFACTURER,
 120        .iProduct =             STRINGID_PRODUCT,
 121        .iSerialNumber =        STRINGID_SERIAL,
 122        .bNumConfigurations =   1,
 123};
 124
 125static struct usb_config_descriptor flash_config0 = {
 126        .bLength                = sizeof(flash_config0),
 127        .bDescriptorType        = USB_DT_CONFIG,
 128
 129        /* wTotalLength is set up by usb-emul-uclass */
 130        .bNumInterfaces         = 1,
 131        .bConfigurationValue    = 0,
 132        .iConfiguration         = 0,
 133        .bmAttributes           = 1 << 7,
 134        .bMaxPower              = 50,
 135};
 136
 137static struct usb_interface_descriptor flash_interface0 = {
 138        .bLength                = sizeof(flash_interface0),
 139        .bDescriptorType        = USB_DT_INTERFACE,
 140
 141        .bInterfaceNumber       = 0,
 142        .bAlternateSetting      = 0,
 143        .bNumEndpoints          = 2,
 144        .bInterfaceClass        = USB_CLASS_MASS_STORAGE,
 145        .bInterfaceSubClass     = US_SC_UFI,
 146        .bInterfaceProtocol     = US_PR_BULK,
 147        .iInterface             = 0,
 148};
 149
 150static struct usb_endpoint_descriptor flash_endpoint0_out = {
 151        .bLength                = USB_DT_ENDPOINT_SIZE,
 152        .bDescriptorType        = USB_DT_ENDPOINT,
 153
 154        .bEndpointAddress       = SANDBOX_FLASH_EP_OUT,
 155        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
 156        .wMaxPacketSize         = __constant_cpu_to_le16(1024),
 157        .bInterval              = 0,
 158};
 159
 160static struct usb_endpoint_descriptor flash_endpoint1_in = {
 161        .bLength                = USB_DT_ENDPOINT_SIZE,
 162        .bDescriptorType        = USB_DT_ENDPOINT,
 163
 164        .bEndpointAddress       = SANDBOX_FLASH_EP_IN | USB_ENDPOINT_DIR_MASK,
 165        .bmAttributes           = USB_ENDPOINT_XFER_BULK,
 166        .wMaxPacketSize         = __constant_cpu_to_le16(1024),
 167        .bInterval              = 0,
 168};
 169
 170static void *flash_desc_list[] = {
 171        &flash_device_desc,
 172        &flash_config0,
 173        &flash_interface0,
 174        &flash_endpoint0_out,
 175        &flash_endpoint1_in,
 176        NULL,
 177};
 178
 179static int sandbox_flash_control(struct udevice *dev, struct usb_device *udev,
 180                                 unsigned long pipe, void *buff, int len,
 181                                 struct devrequest *setup)
 182{
 183        struct sandbox_flash_priv *priv = dev_get_priv(dev);
 184
 185        if (pipe == usb_rcvctrlpipe(udev, 0)) {
 186                switch (setup->request) {
 187                case US_BBB_RESET:
 188                        priv->error = false;
 189                        return 0;
 190                case US_BBB_GET_MAX_LUN:
 191                        *(char *)buff = '\0';
 192                        return 1;
 193                default:
 194                        debug("request=%x\n", setup->request);
 195                        break;
 196                }
 197        }
 198        debug("pipe=%lx\n", pipe);
 199
 200        return -EIO;
 201}
 202
 203static void setup_fail_response(struct sandbox_flash_priv *priv)
 204{
 205        struct umass_bbb_csw *csw = &priv->status;
 206
 207        csw->dCSWSignature = CSWSIGNATURE;
 208        csw->dCSWTag = priv->tag;
 209        csw->dCSWDataResidue = 0;
 210        csw->bCSWStatus = CSWSTATUS_FAILED;
 211        priv->buff_used = 0;
 212}
 213
 214/**
 215 * setup_response() - set up a response to send back to the host
 216 *
 217 * @priv:       Sandbox flash private data
 218 * @resp:       Response to send, or NULL if none
 219 * @size:       Size of response
 220 */
 221static void setup_response(struct sandbox_flash_priv *priv, void *resp,
 222                           int size)
 223{
 224        struct umass_bbb_csw *csw = &priv->status;
 225
 226        csw->dCSWSignature = CSWSIGNATURE;
 227        csw->dCSWTag = priv->tag;
 228        csw->dCSWDataResidue = 0;
 229        csw->bCSWStatus = CSWSTATUS_GOOD;
 230
 231        assert(!resp || resp == priv->buff);
 232        priv->buff_used = size;
 233}
 234
 235static void handle_read(struct sandbox_flash_priv *priv, ulong lba,
 236                        ulong transfer_len)
 237{
 238        debug("%s: lba=%lx, transfer_len=%lx\n", __func__, lba, transfer_len);
 239        if (priv->fd != -1) {
 240                os_lseek(priv->fd, lba * SANDBOX_FLASH_BLOCK_LEN, OS_SEEK_SET);
 241                priv->read_len = transfer_len;
 242                setup_response(priv, priv->buff,
 243                               transfer_len * SANDBOX_FLASH_BLOCK_LEN);
 244        } else {
 245                setup_fail_response(priv);
 246        }
 247}
 248
 249static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff,
 250                              int len)
 251{
 252        const struct SCSI_cmd_block *req = buff;
 253
 254        switch (*req->cmd) {
 255        case SCSI_INQUIRY: {
 256                struct scsi_inquiry_resp *resp = (void *)priv->buff;
 257
 258                priv->alloc_len = req->cmd[4];
 259                memset(resp, '\0', sizeof(*resp));
 260                resp->data_format = 1;
 261                resp->additional_len = 0x1f;
 262                strncpy(resp->vendor,
 263                        flash_strings[STRINGID_MANUFACTURER -  1].s,
 264                        sizeof(resp->vendor));
 265                strncpy(resp->product, flash_strings[STRINGID_PRODUCT - 1].s,
 266                        sizeof(resp->product));
 267                strncpy(resp->revision, "1.0", sizeof(resp->revision));
 268                setup_response(priv, resp, sizeof(*resp));
 269                break;
 270        }
 271        case SCSI_TST_U_RDY:
 272                setup_response(priv, NULL, 0);
 273                break;
 274        case SCSI_RD_CAPAC: {
 275                struct scsi_read_capacity_resp *resp = (void *)priv->buff;
 276                uint blocks;
 277
 278                if (priv->file_size)
 279                        blocks = priv->file_size / SANDBOX_FLASH_BLOCK_LEN - 1;
 280                else
 281                        blocks = 0;
 282                resp->last_block_addr = cpu_to_be32(blocks);
 283                resp->block_len = cpu_to_be32(SANDBOX_FLASH_BLOCK_LEN);
 284                setup_response(priv, resp, sizeof(*resp));
 285                break;
 286        }
 287        case SCSI_READ10: {
 288                struct scsi_read10_req *req = (void *)buff;
 289
 290                handle_read(priv, be32_to_cpu(req->lba),
 291                            be16_to_cpu(req->transfer_len));
 292                break;
 293        }
 294        default:
 295                debug("Command not supported: %x\n", req->cmd[0]);
 296                return -EPROTONOSUPPORT;
 297        }
 298
 299        priv->phase = priv->transfer_len ? PHASE_DATA : PHASE_STATUS;
 300        return 0;
 301}
 302
 303static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev,
 304                              unsigned long pipe, void *buff, int len)
 305{
 306        struct sandbox_flash_priv *priv = dev_get_priv(dev);
 307        int ep = usb_pipeendpoint(pipe);
 308        struct umass_bbb_cbw *cbw = buff;
 309
 310        debug("%s: dev=%s, pipe=%lx, ep=%x, len=%x, phase=%d\n", __func__,
 311              dev->name, pipe, ep, len, priv->phase);
 312        switch (ep) {
 313        case SANDBOX_FLASH_EP_OUT:
 314                switch (priv->phase) {
 315                case PHASE_START:
 316                        priv->alloc_len = 0;
 317                        priv->read_len = 0;
 318                        if (priv->error || len != UMASS_BBB_CBW_SIZE ||
 319                            cbw->dCBWSignature != CBWSIGNATURE)
 320                                goto err;
 321                        if ((cbw->bCBWFlags & CBWFLAGS_SBZ) ||
 322                            cbw->bCBWLUN != 0)
 323                                goto err;
 324                        if (cbw->bCDBLength < 1 || cbw->bCDBLength >= 0x10)
 325                                goto err;
 326                        priv->transfer_len = cbw->dCBWDataTransferLength;
 327                        priv->tag = cbw->dCBWTag;
 328                        return handle_ufi_command(priv, cbw->CBWCDB,
 329                                                  cbw->bCDBLength);
 330                case PHASE_DATA:
 331                        debug("data out\n");
 332                        break;
 333                default:
 334                        break;
 335                }
 336        case SANDBOX_FLASH_EP_IN:
 337                switch (priv->phase) {
 338                case PHASE_DATA:
 339                        debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n",
 340                              len, priv->alloc_len, priv->read_len);
 341                        if (priv->read_len) {
 342                                ulong bytes_read;
 343
 344                                bytes_read = os_read(priv->fd, buff, len);
 345                                if (bytes_read != len)
 346                                        return -EIO;
 347                                priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN;
 348                                if (!priv->read_len)
 349                                        priv->phase = PHASE_STATUS;
 350                        } else {
 351                                if (priv->alloc_len && len > priv->alloc_len)
 352                                        len = priv->alloc_len;
 353                                memcpy(buff, priv->buff, len);
 354                                priv->phase = PHASE_STATUS;
 355                        }
 356                        return len;
 357                case PHASE_STATUS:
 358                        debug("status in, len=%x\n", len);
 359                        if (len > sizeof(priv->status))
 360                                len = sizeof(priv->status);
 361                        memcpy(buff, &priv->status, len);
 362                        priv->phase = PHASE_START;
 363                        return len;
 364                default:
 365                        break;
 366                }
 367        }
 368err:
 369        priv->error = true;
 370        debug("%s: Detected transfer error\n", __func__);
 371        return 0;
 372}
 373
 374static int sandbox_flash_ofdata_to_platdata(struct udevice *dev)
 375{
 376        struct sandbox_flash_plat *plat = dev_get_platdata(dev);
 377        const void *blob = gd->fdt_blob;
 378
 379        plat->pathname = fdt_getprop(blob, dev->of_offset, "sandbox,filepath",
 380                                     NULL);
 381
 382        return 0;
 383}
 384
 385static int sandbox_flash_bind(struct udevice *dev)
 386{
 387        return usb_emul_setup_device(dev, PACKET_SIZE_64, flash_strings,
 388                                     flash_desc_list);
 389}
 390
 391static int sandbox_flash_probe(struct udevice *dev)
 392{
 393        struct sandbox_flash_plat *plat = dev_get_platdata(dev);
 394        struct sandbox_flash_priv *priv = dev_get_priv(dev);
 395
 396        priv->fd = os_open(plat->pathname, OS_O_RDONLY);
 397        if (priv->fd != -1)
 398                return os_get_filesize(plat->pathname, &priv->file_size);
 399
 400        return 0;
 401}
 402
 403static const struct dm_usb_ops sandbox_usb_flash_ops = {
 404        .control        = sandbox_flash_control,
 405        .bulk           = sandbox_flash_bulk,
 406};
 407
 408static const struct udevice_id sandbox_usb_flash_ids[] = {
 409        { .compatible = "sandbox,usb-flash" },
 410        { }
 411};
 412
 413U_BOOT_DRIVER(usb_sandbox_flash) = {
 414        .name   = "usb_sandbox_flash",
 415        .id     = UCLASS_USB_EMUL,
 416        .of_match = sandbox_usb_flash_ids,
 417        .bind   = sandbox_flash_bind,
 418        .probe  = sandbox_flash_probe,
 419        .ofdata_to_platdata = sandbox_flash_ofdata_to_platdata,
 420        .ops    = &sandbox_usb_flash_ops,
 421        .priv_auto_alloc_size = sizeof(struct sandbox_flash_priv),
 422        .platdata_auto_alloc_size = sizeof(struct sandbox_flash_plat),
 423};
 424