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