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