[PATCH 00/15] scsi: Convert sandbox SCSI to driver model

This series moves sandbox over to use driver model for SCSI. It takes the opportunity to use common code with the USB flash driver.
This is mostly refactoring, but there is a small amount of new code, notably a test which checks that data can be read from a SCSI device.
Simon Glass (15): scsi: Tidy up comments for struct scsi_cmd sandbox: usb: Rename transfer_len in protocol struct scsi: Move cmd_phase enum to the header scsi: Move core emulation state into a new struct sandbox: Move buffer to scsi_emul_info scsi: Move vendor/product info into the shared struct sandbox: scsi: Move block size into shared struct sandbox: scsi: Move file size into shared struct sandbox: scsi: Move reply setup out of helper sandbox: scsi: Remove setup calls from handle_read() sandbox: scsi: Move structs to header file sandbox: Enable SCSI for all builds sandbox: scsi: Move request-handling code to scsi_emul sandbox: Convert to use driver model for SCSI sandbox: Add a test for SCSI
arch/Kconfig | 1 - arch/sandbox/dts/sandbox.dtsi | 4 + arch/sandbox/dts/test.dts | 5 + configs/sandbox64_defconfig | 6 + configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 5 + configs/sandbox_noinst_defconfig | 5 + configs/sandbox_spl_defconfig | 7 +- configs/sandbox_vpl_defconfig | 5 + drivers/scsi/Makefile | 1 + drivers/scsi/sandbox_scsi.c | 132 +++++++++++++++++- drivers/scsi/scsi_emul.c | 74 +++++++++++ drivers/usb/emul/sandbox_flash.c | 207 ++++++++++------------------- include/scsi.h | 68 +++++++--- include/scsi_emul.h | 70 ++++++++++ test/dm/Makefile | 1 + test/dm/scsi.c | 39 ++++++ test/py/tests/test_ut.py | 9 ++ 18 files changed, 478 insertions(+), 162 deletions(-) create mode 100644 drivers/scsi/scsi_emul.c create mode 100644 include/scsi_emul.h create mode 100644 test/dm/scsi.c

These comments are bit of a mess. Tidy them up to match the correct coding style.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/scsi.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/scsi.h b/include/scsi.h index b47c7463c1d..e5d75b0cdca 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -16,26 +16,26 @@ struct udevice;
struct scsi_cmd { - unsigned char cmd[16]; /* command */ + unsigned char cmd[16]; /* command */ /* for request sense */ - unsigned char sense_buf[64] + unsigned char sense_buf[64] __attribute__((aligned(ARCH_DMA_MINALIGN))); - unsigned char status; /* SCSI Status */ - unsigned char target; /* Target ID */ - unsigned char lun; /* Target LUN */ - unsigned char cmdlen; /* command len */ - unsigned long datalen; /* Total data length */ - unsigned char * pdata; /* pointer to data */ - unsigned char msgout[12]; /* Messge out buffer (NOT USED) */ - unsigned char msgin[12]; /* Message in buffer */ - unsigned char sensecmdlen; /* Sense command len */ - unsigned long sensedatalen; /* Sense data len */ - unsigned char sensecmd[6]; /* Sense command */ - unsigned long contr_stat; /* Controller Status */ - unsigned long trans_bytes; /* tranfered bytes */ + unsigned char status; /* SCSI Status */ + unsigned char target; /* Target ID */ + unsigned char lun; /* Target LUN */ + unsigned char cmdlen; /* command len */ + unsigned long datalen; /* Total data length */ + unsigned char *pdata; /* pointer to data */ + unsigned char msgout[12]; /* Messge out buffer (NOT USED) */ + unsigned char msgin[12]; /* Message in buffer */ + unsigned char sensecmdlen; /* Sense command len */ + unsigned long sensedatalen; /* Sense data len */ + unsigned char sensecmd[6]; /* Sense command */ + unsigned long contr_stat; /* Controller Status */ + unsigned long trans_bytes; /* tranfered bytes */
- unsigned int priv; - enum dma_data_direction dma_dir; + unsigned int priv; + enum dma_data_direction dma_dir; };
/*-----------------------------------------------------------

On 8/27/22 17:14, Simon Glass wrote:
These comments are bit of a mess. Tidy them up to match the correct coding style.
Signed-off-by: Simon Glass sjg@chromium.org
It would be preferable to use Sphinx style comments as you already did in include/asm-generic/global_data.h.
Best regards
Heinrich
include/scsi.h | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/include/scsi.h b/include/scsi.h index b47c7463c1d..e5d75b0cdca 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -16,26 +16,26 @@ struct udevice;
struct scsi_cmd {
- unsigned char cmd[16]; /* command */
- unsigned char cmd[16]; /* command */ /* for request sense */
- unsigned char sense_buf[64]
- unsigned char sense_buf[64] __attribute__((aligned(ARCH_DMA_MINALIGN)));
- unsigned char status; /* SCSI Status */
- unsigned char target; /* Target ID */
- unsigned char lun; /* Target LUN */
- unsigned char cmdlen; /* command len */
- unsigned long datalen; /* Total data length */
- unsigned char * pdata; /* pointer to data */
- unsigned char msgout[12]; /* Messge out buffer (NOT USED) */
- unsigned char msgin[12]; /* Message in buffer */
- unsigned char sensecmdlen; /* Sense command len */
- unsigned long sensedatalen; /* Sense data len */
- unsigned char sensecmd[6]; /* Sense command */
- unsigned long contr_stat; /* Controller Status */
- unsigned long trans_bytes; /* tranfered bytes */
- unsigned char status; /* SCSI Status */
- unsigned char target; /* Target ID */
- unsigned char lun; /* Target LUN */
- unsigned char cmdlen; /* command len */
- unsigned long datalen; /* Total data length */
- unsigned char *pdata; /* pointer to data */
- unsigned char msgout[12]; /* Messge out buffer (NOT USED) */
- unsigned char msgin[12]; /* Message in buffer */
- unsigned char sensecmdlen; /* Sense command len */
- unsigned long sensedatalen; /* Sense data len */
- unsigned char sensecmd[6]; /* Sense command */
- unsigned long contr_stat; /* Controller Status */
- unsigned long trans_bytes; /* tranfered bytes */
- unsigned int priv;
- enum dma_data_direction dma_dir;
unsigned int priv;
enum dma_data_direction dma_dir; };
/*-----------------------------------------------------------

This has the same name as a field in our local private struct, which is confusing. Change the name to xfer_len instead.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 01b2b41cce9..7de752100c8 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -43,7 +43,7 @@ enum { * @error: true if there is an error condition * @alloc_len: Allocation length from the last incoming command * @transfer_len: Transfer length from CBW header - * @read_len: Number of blocks of data left in the current read command + * @read_len: Number of bytes of data left in the current read command * @tag: Tag value from last command * @fd: File descriptor of backing file * @file_size: Size of file in bytes @@ -92,7 +92,7 @@ struct __packed scsi_read10_req { u8 lun_flags; u32 lba; u8 spare; - u16 transfer_len; + u16 xfer_len; u8 spare2[3]; };
@@ -282,7 +282,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct scsi_read10_req *req = (void *)buff;
handle_read(priv, be32_to_cpu(req->lba), - be16_to_cpu(req->transfer_len)); + be16_to_cpu(req->xfer_len)); break; } default:

This can be used by common files, so move it to the SCSI header and rename it.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 24 +++++++++--------------- include/scsi.h | 6 ++++++ 2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 7de752100c8..806aed2ef2e 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -23,12 +23,6 @@ enum { SANDBOX_FLASH_BLOCK_LEN = 512, };
-enum cmd_phase { - PHASE_START, - PHASE_DATA, - PHASE_STATUS, -}; - enum { STRINGID_MANUFACTURER = 1, STRINGID_PRODUCT, @@ -56,7 +50,7 @@ struct sandbox_flash_priv { int alloc_len; int transfer_len; int read_len; - enum cmd_phase phase; + enum scsi_cmd_phase phase; u32 tag; int fd; loff_t file_size; @@ -290,7 +284,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, return -EPROTONOSUPPORT; }
- priv->phase = priv->transfer_len ? PHASE_DATA : PHASE_STATUS; + priv->phase = priv->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; return 0; }
@@ -307,7 +301,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, switch (ep) { case SANDBOX_FLASH_EP_OUT: switch (priv->phase) { - case PHASE_START: + case SCSIPH_START: priv->alloc_len = 0; priv->read_len = 0; if (priv->error || len != UMASS_BBB_CBW_SIZE || @@ -322,7 +316,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, priv->tag = cbw->dCBWTag; return handle_ufi_command(plat, priv, cbw->CBWCDB, cbw->bCDBLength); - case PHASE_DATA: + case SCSIPH_DATA: debug("data out\n"); break; default: @@ -330,7 +324,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, } case SANDBOX_FLASH_EP_IN: switch (priv->phase) { - case PHASE_DATA: + case SCSIPH_DATA: debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n", len, priv->alloc_len, priv->read_len); if (priv->read_len) { @@ -344,22 +338,22 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, return -EIO; priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; if (!priv->read_len) - priv->phase = PHASE_STATUS; + priv->phase = SCSIPH_STATUS; } else { if (priv->alloc_len && len > priv->alloc_len) len = priv->alloc_len; if (len > sizeof(priv->buff)) len = sizeof(priv->buff); memcpy(buff, priv->buff, len); - priv->phase = PHASE_STATUS; + priv->phase = SCSIPH_STATUS; } return len; - case PHASE_STATUS: + case SCSIPH_STATUS: debug("status in, len=%x\n", len); if (len > sizeof(priv->status)) len = sizeof(priv->status); memcpy(buff, &priv->status, len); - priv->phase = PHASE_START; + priv->phase = SCSIPH_START; return len; default: break; diff --git a/include/scsi.h b/include/scsi.h index e5d75b0cdca..5d63963bed0 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -167,6 +167,12 @@ struct scsi_cmd { #define SCSI_WRITE_LONG 0x3F /* Write Long (O) */ #define SCSI_WRITE_SAME 0x41 /* Write Same (O) */
+enum scsi_cmd_phase { + SCSIPH_START, + SCSIPH_DATA, + SCSIPH_STATUS, +}; + /** * struct scsi_plat - stores information about SCSI controller *

On 8/27/22 17:15, Simon Glass wrote:
This can be used by common files, so move it to the SCSI header and rename it.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/usb/emul/sandbox_flash.c | 24 +++++++++--------------- include/scsi.h | 6 ++++++ 2 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 7de752100c8..806aed2ef2e 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -23,12 +23,6 @@ enum { SANDBOX_FLASH_BLOCK_LEN = 512, };
-enum cmd_phase {
- PHASE_START,
- PHASE_DATA,
- PHASE_STATUS,
-};
- enum { STRINGID_MANUFACTURER = 1, STRINGID_PRODUCT,
@@ -56,7 +50,7 @@ struct sandbox_flash_priv { int alloc_len; int transfer_len; int read_len;
- enum cmd_phase phase;
- enum scsi_cmd_phase phase; u32 tag; int fd; loff_t file_size;
@@ -290,7 +284,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, return -EPROTONOSUPPORT; }
- priv->phase = priv->transfer_len ? PHASE_DATA : PHASE_STATUS;
- priv->phase = priv->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; return 0; }
@@ -307,7 +301,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, switch (ep) { case SANDBOX_FLASH_EP_OUT: switch (priv->phase) {
case PHASE_START:
case SCSIPH_START: priv->alloc_len = 0; priv->read_len = 0; if (priv->error || len != UMASS_BBB_CBW_SIZE ||
@@ -322,7 +316,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, priv->tag = cbw->dCBWTag; return handle_ufi_command(plat, priv, cbw->CBWCDB, cbw->bCDBLength);
case PHASE_DATA:
default:case SCSIPH_DATA: debug("data out\n"); break;
@@ -330,7 +324,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, } case SANDBOX_FLASH_EP_IN: switch (priv->phase) {
case PHASE_DATA:
case SCSIPH_DATA: debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n", len, priv->alloc_len, priv->read_len); if (priv->read_len) {
@@ -344,22 +338,22 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, return -EIO; priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; if (!priv->read_len)
priv->phase = PHASE_STATUS;
priv->phase = SCSIPH_STATUS; } else { if (priv->alloc_len && len > priv->alloc_len) len = priv->alloc_len; if (len > sizeof(priv->buff)) len = sizeof(priv->buff); memcpy(buff, priv->buff, len);
priv->phase = PHASE_STATUS;
priv->phase = SCSIPH_STATUS; } return len;
case PHASE_STATUS:
case SCSIPH_STATUS: debug("status in, len=%x\n", len); if (len > sizeof(priv->status)) len = sizeof(priv->status); memcpy(buff, &priv->status, len);
priv->phase = PHASE_START;
default: break;priv->phase = SCSIPH_START; return len;
diff --git a/include/scsi.h b/include/scsi.h index e5d75b0cdca..5d63963bed0 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -167,6 +167,12 @@ struct scsi_cmd { #define SCSI_WRITE_LONG 0x3F /* Write Long (O) */ #define SCSI_WRITE_SAME 0x41 /* Write Same (O) */
+enum scsi_cmd_phase {
Please, add Sphinx style description.
Best regards
Heinrich
- SCSIPH_START,
- SCSIPH_DATA,
- SCSIPH_STATUS,
+};
- /**
- struct scsi_plat - stores information about SCSI controller

In preparation for sharing the emulation code between two drivers, move some of the fields into a new struct. Use a separate header file so it can be used by various drivers.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 60 ++++++++++++++++---------------- include/scsi_emul.h | 32 +++++++++++++++++ 2 files changed, 62 insertions(+), 30 deletions(-) create mode 100644 include/scsi_emul.h
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 806aed2ef2e..e7abc0d5c9f 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -9,6 +9,7 @@ #include <log.h> #include <os.h> #include <scsi.h> +#include <scsi_emul.h> #include <usb.h>
/* @@ -34,28 +35,21 @@ enum { /** * struct sandbox_flash_priv - private state for this driver * + * @eminfo: emulator state * @error: true if there is an error condition - * @alloc_len: Allocation length from the last incoming command - * @transfer_len: Transfer length from CBW header - * @read_len: Number of bytes of data left in the current read command * @tag: Tag value from last command * @fd: File descriptor of backing file * @file_size: Size of file in bytes * @status_buff: Data buffer for outgoing status - * @buff_used: Number of bytes ready to transfer back to host * @buff: Data buffer for outgoing data */ struct sandbox_flash_priv { + struct scsi_emul_info eminfo; bool error; - int alloc_len; - int transfer_len; - int read_len; - enum scsi_cmd_phase phase; u32 tag; int fd; loff_t file_size; struct umass_bbb_csw status; - int buff_used; u8 buff[512]; };
@@ -188,13 +182,14 @@ static int sandbox_flash_control(struct udevice *dev, struct usb_device *udev,
static void setup_fail_response(struct sandbox_flash_priv *priv) { + struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status;
csw->dCSWSignature = CSWSIGNATURE; csw->dCSWTag = priv->tag; csw->dCSWDataResidue = 0; csw->bCSWStatus = CSWSTATUS_FAILED; - priv->buff_used = 0; + info->buff_used = 0; }
/** @@ -207,6 +202,7 @@ static void setup_fail_response(struct sandbox_flash_priv *priv) static void setup_response(struct sandbox_flash_priv *priv, void *resp, int size) { + struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status;
csw->dCSWSignature = CSWSIGNATURE; @@ -215,14 +211,16 @@ static void setup_response(struct sandbox_flash_priv *priv, void *resp, csw->bCSWStatus = CSWSTATUS_GOOD;
assert(!resp || resp == priv->buff); - priv->buff_used = size; + info->buff_used = size; }
static void handle_read(struct sandbox_flash_priv *priv, ulong lba, ulong transfer_len) { + struct scsi_emul_info *info = &priv->eminfo; + debug("%s: lba=%lx, transfer_len=%lx\n", __func__, lba, transfer_len); - priv->read_len = transfer_len; + info->read_len = transfer_len; if (priv->fd != -1) { os_lseek(priv->fd, lba * SANDBOX_FLASH_BLOCK_LEN, OS_SEEK_SET); setup_response(priv, priv->buff, @@ -236,13 +234,14 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct sandbox_flash_priv *priv, const void *buff, int len) { + struct scsi_emul_info *info = &priv->eminfo; const struct scsi_cmd *req = buff;
switch (*req->cmd) { case SCSI_INQUIRY: { struct scsi_inquiry_resp *resp = (void *)priv->buff;
- priv->alloc_len = req->cmd[4]; + info->alloc_len = req->cmd[4]; memset(resp, '\0', sizeof(*resp)); resp->data_format = 1; resp->additional_len = 0x1f; @@ -284,7 +283,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, return -EPROTONOSUPPORT; }
- priv->phase = priv->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; + info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; return 0; }
@@ -293,17 +292,18 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, { struct sandbox_flash_plat *plat = dev_get_plat(dev); struct sandbox_flash_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; int ep = usb_pipeendpoint(pipe); struct umass_bbb_cbw *cbw = buff;
debug("%s: dev=%s, pipe=%lx, ep=%x, len=%x, phase=%d\n", __func__, - dev->name, pipe, ep, len, priv->phase); + dev->name, pipe, ep, len, info->phase); switch (ep) { case SANDBOX_FLASH_EP_OUT: - switch (priv->phase) { + switch (info->phase) { case SCSIPH_START: - priv->alloc_len = 0; - priv->read_len = 0; + info->alloc_len = 0; + info->read_len = 0; if (priv->error || len != UMASS_BBB_CBW_SIZE || cbw->dCBWSignature != CBWSIGNATURE) goto err; @@ -312,7 +312,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, goto err; if (cbw->bCDBLength < 1 || cbw->bCDBLength >= 0x10) goto err; - priv->transfer_len = cbw->dCBWDataTransferLength; + info->transfer_len = cbw->dCBWDataTransferLength; priv->tag = cbw->dCBWTag; return handle_ufi_command(plat, priv, cbw->CBWCDB, cbw->bCDBLength); @@ -323,11 +323,11 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, break; } case SANDBOX_FLASH_EP_IN: - switch (priv->phase) { + switch (info->phase) { case SCSIPH_DATA: - debug("data in, len=%x, alloc_len=%x, priv->read_len=%x\n", - len, priv->alloc_len, priv->read_len); - if (priv->read_len) { + debug("data in, len=%x, alloc_len=%x, info->read_len=%x\n", + len, info->alloc_len, info->read_len); + if (info->read_len) { ulong bytes_read;
if (priv->fd == -1) @@ -336,16 +336,16 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, bytes_read = os_read(priv->fd, buff, len); if (bytes_read != len) return -EIO; - priv->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; - if (!priv->read_len) - priv->phase = SCSIPH_STATUS; + info->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; + if (!info->read_len) + info->phase = SCSIPH_STATUS; } else { - if (priv->alloc_len && len > priv->alloc_len) - len = priv->alloc_len; + if (info->alloc_len && len > info->alloc_len) + len = info->alloc_len; if (len > sizeof(priv->buff)) len = sizeof(priv->buff); memcpy(buff, priv->buff, len); - priv->phase = SCSIPH_STATUS; + info->phase = SCSIPH_STATUS; } return len; case SCSIPH_STATUS: @@ -353,7 +353,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, if (len > sizeof(priv->status)) len = sizeof(priv->status); memcpy(buff, &priv->status, len); - priv->phase = SCSIPH_START; + info->phase = SCSIPH_START; return len; default: break; diff --git a/include/scsi_emul.h b/include/scsi_emul.h new file mode 100644 index 00000000000..dec78d239c7 --- /dev/null +++ b/include/scsi_emul.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Emulation of enough SCSI commands to find and read from a unit + * + * Copyright 2022 Google LLC + * Written by Simon Glass sjg@chromium.org + * + * implementations of SCSI functions required so that CONFIG_SCSI can be enabled + * for sandbox + */ + +#ifndef __scsi_emul_h +#define __scsi_emul_h + +/** + * struct scsi_emul_info - information for emulating a SCSI device + * + * @phase: Current SCSI phase + * @buff_used: Number of bytes ready to transfer back to host + * @read_len: Number of bytes of data left in the current read command + * @alloc_len: Allocation length from the last incoming command + * @transfer_len: Transfer length from CBW header + */ +struct scsi_emul_info { + enum scsi_cmd_phase phase; + int buff_used; + int read_len; + int alloc_len; + uint transfer_len; +}; + +#endif

Move the buffer into this struct so it can be shared between different implementations.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 41 +++++++++++++++++++++++--------- include/scsi_emul.h | 5 ++++ 2 files changed, 35 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index e7abc0d5c9f..3a9db835eed 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -7,6 +7,7 @@ #include <common.h> #include <dm.h> #include <log.h> +#include <malloc.h> #include <os.h> #include <scsi.h> #include <scsi_emul.h> @@ -22,6 +23,7 @@ enum { SANDBOX_FLASH_EP_OUT = 1, /* endpoints */ SANDBOX_FLASH_EP_IN = 2, SANDBOX_FLASH_BLOCK_LEN = 512, + SANDBOX_FLASH_BUF_SIZE = 512, };
enum { @@ -41,7 +43,6 @@ enum { * @fd: File descriptor of backing file * @file_size: Size of file in bytes * @status_buff: Data buffer for outgoing status - * @buff: Data buffer for outgoing data */ struct sandbox_flash_priv { struct scsi_emul_info eminfo; @@ -50,7 +51,6 @@ struct sandbox_flash_priv { int fd; loff_t file_size; struct umass_bbb_csw status; - u8 buff[512]; };
struct sandbox_flash_plat { @@ -210,7 +210,7 @@ static void setup_response(struct sandbox_flash_priv *priv, void *resp, csw->dCSWDataResidue = 0; csw->bCSWStatus = CSWSTATUS_GOOD;
- assert(!resp || resp == priv->buff); + assert(!resp || resp == info->buff); info->buff_used = size; }
@@ -223,7 +223,7 @@ static void handle_read(struct sandbox_flash_priv *priv, ulong lba, info->read_len = transfer_len; if (priv->fd != -1) { os_lseek(priv->fd, lba * SANDBOX_FLASH_BLOCK_LEN, OS_SEEK_SET); - setup_response(priv, priv->buff, + setup_response(priv, info->buff, transfer_len * SANDBOX_FLASH_BLOCK_LEN); } else { setup_fail_response(priv); @@ -239,7 +239,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat,
switch (*req->cmd) { case SCSI_INQUIRY: { - struct scsi_inquiry_resp *resp = (void *)priv->buff; + struct scsi_inquiry_resp *resp = (void *)info->buff;
info->alloc_len = req->cmd[4]; memset(resp, '\0', sizeof(*resp)); @@ -259,7 +259,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, setup_response(priv, NULL, 0); break; case SCSI_RD_CAPAC: { - struct scsi_read_capacity_resp *resp = (void *)priv->buff; + struct scsi_read_capacity_resp *resp = (void *)info->buff; uint blocks;
if (priv->file_size) @@ -342,9 +342,9 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, } else { if (info->alloc_len && len > info->alloc_len) len = info->alloc_len; - if (len > sizeof(priv->buff)) - len = sizeof(priv->buff); - memcpy(buff, priv->buff, len); + if (len > SANDBOX_FLASH_BUF_SIZE) + len = SANDBOX_FLASH_BUF_SIZE; + memcpy(buff, info->buff, len); info->phase = SCSIPH_STATUS; } return len; @@ -394,10 +394,28 @@ static int sandbox_flash_probe(struct udevice *dev) { struct sandbox_flash_plat *plat = dev_get_plat(dev); struct sandbox_flash_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; + int ret;
priv->fd = os_open(plat->pathname, OS_O_RDONLY); - if (priv->fd != -1) - return os_get_filesize(plat->pathname, &priv->file_size); + if (priv->fd != -1) { + ret = os_get_filesize(plat->pathname, &priv->file_size); + if (ret) + return log_msg_ret("sz", ret); + } + info->buff = malloc(SANDBOX_FLASH_BUF_SIZE); + if (!info->buff) + return log_ret(-ENOMEM); + + return 0; +} + +static int sandbox_flash_remove(struct udevice *dev) +{ + struct sandbox_flash_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; + + free(info->buff);
return 0; } @@ -418,6 +436,7 @@ U_BOOT_DRIVER(usb_sandbox_flash) = { .of_match = sandbox_usb_flash_ids, .bind = sandbox_flash_bind, .probe = sandbox_flash_probe, + .remove = sandbox_flash_remove, .of_to_plat = sandbox_flash_of_to_plat, .ops = &sandbox_usb_flash_ops, .priv_auto = sizeof(struct sandbox_flash_priv), diff --git a/include/scsi_emul.h b/include/scsi_emul.h index dec78d239c7..f27c19750b0 100644 --- a/include/scsi_emul.h +++ b/include/scsi_emul.h @@ -20,8 +20,13 @@ * @read_len: Number of bytes of data left in the current read command * @alloc_len: Allocation length from the last incoming command * @transfer_len: Transfer length from CBW header + * @buff: Data buffer for outgoing data */ struct scsi_emul_info { + /* provided by the caller: */ + void *buff; + + /* state maintained by the emulator: */ enum scsi_cmd_phase phase; int buff_used; int read_len;

Move this information into struct scsi_emul_info so we can use it in common code.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 10 ++++------ include/scsi_emul.h | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 3a9db835eed..eaa7f1e7ff6 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -245,12 +245,8 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, memset(resp, '\0', sizeof(*resp)); resp->data_format = 1; resp->additional_len = 0x1f; - strncpy(resp->vendor, - plat->flash_strings[STRINGID_MANUFACTURER - 1].s, - sizeof(resp->vendor)); - strncpy(resp->product, - plat->flash_strings[STRINGID_PRODUCT - 1].s, - sizeof(resp->product)); + strncpy(resp->vendor, info->vendor, sizeof(resp->vendor)); + strncpy(resp->product, info->product, sizeof(resp->product)); strncpy(resp->revision, "1.0", sizeof(resp->revision)); setup_response(priv, resp, sizeof(*resp)); break; @@ -406,6 +402,8 @@ static int sandbox_flash_probe(struct udevice *dev) info->buff = malloc(SANDBOX_FLASH_BUF_SIZE); if (!info->buff) return log_ret(-ENOMEM); + info->vendor = plat->flash_strings[STRINGID_MANUFACTURER - 1].s; + info->product = plat->flash_strings[STRINGID_PRODUCT - 1].s;
return 0; } diff --git a/include/scsi_emul.h b/include/scsi_emul.h index f27c19750b0..b281c166f6f 100644 --- a/include/scsi_emul.h +++ b/include/scsi_emul.h @@ -15,6 +15,9 @@ /** * struct scsi_emul_info - information for emulating a SCSI device * + * @vendor: Vendor name + * @product: Product name + * * @phase: Current SCSI phase * @buff_used: Number of bytes ready to transfer back to host * @read_len: Number of bytes of data left in the current read command @@ -25,6 +28,8 @@ struct scsi_emul_info { /* provided by the caller: */ void *buff; + const char *vendor; + const char *product;
/* state maintained by the emulator: */ enum scsi_cmd_phase phase;

Move this information into struct scsi_emul_info so we can use it in common code.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 11 ++++++----- include/scsi_emul.h | 2 ++ 2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index eaa7f1e7ff6..e4a8eb2e988 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -222,9 +222,9 @@ static void handle_read(struct sandbox_flash_priv *priv, ulong lba, debug("%s: lba=%lx, transfer_len=%lx\n", __func__, lba, transfer_len); info->read_len = transfer_len; if (priv->fd != -1) { - os_lseek(priv->fd, lba * SANDBOX_FLASH_BLOCK_LEN, OS_SEEK_SET); + os_lseek(priv->fd, lba * info->block_size, OS_SEEK_SET); setup_response(priv, info->buff, - transfer_len * SANDBOX_FLASH_BLOCK_LEN); + transfer_len * info->block_size); } else { setup_fail_response(priv); } @@ -259,11 +259,11 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, uint blocks;
if (priv->file_size) - blocks = priv->file_size / SANDBOX_FLASH_BLOCK_LEN - 1; + blocks = priv->file_size / info->block_size - 1; else blocks = 0; resp->last_block_addr = cpu_to_be32(blocks); - resp->block_len = cpu_to_be32(SANDBOX_FLASH_BLOCK_LEN); + resp->block_len = cpu_to_be32(info->block_size); setup_response(priv, resp, sizeof(*resp)); break; } @@ -332,7 +332,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, bytes_read = os_read(priv->fd, buff, len); if (bytes_read != len) return -EIO; - info->read_len -= len / SANDBOX_FLASH_BLOCK_LEN; + info->read_len -= len / info->block_size; if (!info->read_len) info->phase = SCSIPH_STATUS; } else { @@ -404,6 +404,7 @@ static int sandbox_flash_probe(struct udevice *dev) return log_ret(-ENOMEM); info->vendor = plat->flash_strings[STRINGID_MANUFACTURER - 1].s; info->product = plat->flash_strings[STRINGID_PRODUCT - 1].s; + info->block_size = SANDBOX_FLASH_BLOCK_LEN;
return 0; } diff --git a/include/scsi_emul.h b/include/scsi_emul.h index b281c166f6f..86c9379ca9e 100644 --- a/include/scsi_emul.h +++ b/include/scsi_emul.h @@ -17,6 +17,7 @@ * * @vendor: Vendor name * @product: Product name + * @block_size: Block size of device in bytes (normally 512) * * @phase: Current SCSI phase * @buff_used: Number of bytes ready to transfer back to host @@ -30,6 +31,7 @@ struct scsi_emul_info { void *buff; const char *vendor; const char *product; + int block_size;
/* state maintained by the emulator: */ enum scsi_cmd_phase phase;

Move this information into struct scsi_emul_info so we can use it in common code.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 7 +++---- include/scsi_emul.h | 2 ++ 2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index e4a8eb2e988..3c5bc675e3c 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -49,7 +49,6 @@ struct sandbox_flash_priv { bool error; u32 tag; int fd; - loff_t file_size; struct umass_bbb_csw status; };
@@ -258,8 +257,8 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct scsi_read_capacity_resp *resp = (void *)info->buff; uint blocks;
- if (priv->file_size) - blocks = priv->file_size / info->block_size - 1; + if (info->file_size) + blocks = info->file_size / info->block_size - 1; else blocks = 0; resp->last_block_addr = cpu_to_be32(blocks); @@ -395,7 +394,7 @@ static int sandbox_flash_probe(struct udevice *dev)
priv->fd = os_open(plat->pathname, OS_O_RDONLY); if (priv->fd != -1) { - ret = os_get_filesize(plat->pathname, &priv->file_size); + ret = os_get_filesize(plat->pathname, &info->file_size); if (ret) return log_msg_ret("sz", ret); } diff --git a/include/scsi_emul.h b/include/scsi_emul.h index 86c9379ca9e..3c52398e3ff 100644 --- a/include/scsi_emul.h +++ b/include/scsi_emul.h @@ -18,6 +18,7 @@ * @vendor: Vendor name * @product: Product name * @block_size: Block size of device in bytes (normally 512) + * @file_size: Size of the backing file for this emulator, in bytes * * @phase: Current SCSI phase * @buff_used: Number of bytes ready to transfer back to host @@ -32,6 +33,7 @@ struct scsi_emul_info { const char *vendor; const char *product; int block_size; + loff_t file_size;
/* state maintained by the emulator: */ enum scsi_cmd_phase phase;

Move this code out of the helper function so we can (later) add it as part of the shared emulation code. Set a default value of 0 for buff_used since that is what we use when there is an error.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 3c5bc675e3c..e699f89793d 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -181,14 +181,12 @@ static int sandbox_flash_control(struct udevice *dev, struct usb_device *udev,
static void setup_fail_response(struct sandbox_flash_priv *priv) { - struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status;
csw->dCSWSignature = CSWSIGNATURE; csw->dCSWTag = priv->tag; csw->dCSWDataResidue = 0; csw->bCSWStatus = CSWSTATUS_FAILED; - info->buff_used = 0; }
/** @@ -198,19 +196,14 @@ static void setup_fail_response(struct sandbox_flash_priv *priv) * @resp: Response to send, or NULL if none * @size: Size of response */ -static void setup_response(struct sandbox_flash_priv *priv, void *resp, - int size) +static void setup_response(struct sandbox_flash_priv *priv) { - struct scsi_emul_info *info = &priv->eminfo; struct umass_bbb_csw *csw = &priv->status;
csw->dCSWSignature = CSWSIGNATURE; csw->dCSWTag = priv->tag; csw->dCSWDataResidue = 0; csw->bCSWStatus = CSWSTATUS_GOOD; - - assert(!resp || resp == info->buff); - info->buff_used = size; }
static void handle_read(struct sandbox_flash_priv *priv, ulong lba, @@ -222,8 +215,8 @@ static void handle_read(struct sandbox_flash_priv *priv, ulong lba, info->read_len = transfer_len; if (priv->fd != -1) { os_lseek(priv->fd, lba * info->block_size, OS_SEEK_SET); - setup_response(priv, info->buff, - transfer_len * info->block_size); + info->buff_used = transfer_len * info->block_size; + setup_response(priv); } else { setup_fail_response(priv); } @@ -236,6 +229,7 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, struct scsi_emul_info *info = &priv->eminfo; const struct scsi_cmd *req = buff;
+ info->buff_used = 0; switch (*req->cmd) { case SCSI_INQUIRY: { struct scsi_inquiry_resp *resp = (void *)info->buff; @@ -247,11 +241,12 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, strncpy(resp->vendor, info->vendor, sizeof(resp->vendor)); strncpy(resp->product, info->product, sizeof(resp->product)); strncpy(resp->revision, "1.0", sizeof(resp->revision)); - setup_response(priv, resp, sizeof(*resp)); + info->buff_used = sizeof(*resp); + setup_response(priv); break; } case SCSI_TST_U_RDY: - setup_response(priv, NULL, 0); + setup_response(priv); break; case SCSI_RD_CAPAC: { struct scsi_read_capacity_resp *resp = (void *)info->buff; @@ -263,7 +258,8 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, blocks = 0; resp->last_block_addr = cpu_to_be32(blocks); resp->block_len = cpu_to_be32(info->block_size); - setup_response(priv, resp, sizeof(*resp)); + info->buff_used = sizeof(*resp); + setup_response(priv); break; } case SCSI_READ10: {

Move the device-specific code out into the top-level function.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index e699f89793d..7b9a99c1a38 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -206,8 +206,19 @@ static void setup_response(struct sandbox_flash_priv *priv) csw->bCSWStatus = CSWSTATUS_GOOD; }
-static void handle_read(struct sandbox_flash_priv *priv, ulong lba, - ulong transfer_len) +/** + * handle_read() - prepare for reading data from the backing file + * + * This seeks to the correct file position and sets info->buff_used to the + * correct size. + * + * @priv: Private information + * @lba: Start block to read from + * @transfer_length: Number of blocks to read + * @return 0 if OK, -EIO on failure + */ +static int handle_read(struct sandbox_flash_priv *priv, ulong lba, + ulong transfer_len) { struct scsi_emul_info *info = &priv->eminfo;
@@ -216,10 +227,10 @@ static void handle_read(struct sandbox_flash_priv *priv, ulong lba, if (priv->fd != -1) { os_lseek(priv->fd, lba * info->block_size, OS_SEEK_SET); info->buff_used = transfer_len * info->block_size; - setup_response(priv); - } else { - setup_fail_response(priv); + return 0; } + + return -EIO; }
static int handle_ufi_command(struct sandbox_flash_plat *plat, @@ -265,8 +276,12 @@ static int handle_ufi_command(struct sandbox_flash_plat *plat, case SCSI_READ10: { struct scsi_read10_req *req = (void *)buff;
- handle_read(priv, be32_to_cpu(req->lba), - be16_to_cpu(req->xfer_len)); + if (!handle_read(priv, be32_to_cpu(req->lba), + be16_to_cpu(req->xfer_len))) + setup_response(priv); + else + setup_fail_response(priv); + break; } default:

Move these to the SCSI header file so we can access them from multiple emulators.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/usb/emul/sandbox_flash.c | 26 -------------------------- include/scsi.h | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 7b9a99c1a38..2059fc7fe42 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -57,32 +57,6 @@ struct sandbox_flash_plat { struct usb_string flash_strings[STRINGID_COUNT]; };
-struct scsi_inquiry_resp { - u8 type; - u8 flags; - u8 version; - u8 data_format; - u8 additional_len; - u8 spare[3]; - char vendor[8]; - char product[16]; - char revision[4]; -}; - -struct scsi_read_capacity_resp { - u32 last_block_addr; - u32 block_len; -}; - -struct __packed scsi_read10_req { - u8 cmd; - u8 lun_flags; - u32 lba; - u8 spare; - u16 xfer_len; - u8 spare2[3]; -}; - static struct usb_device_descriptor flash_device_desc = { .bLength = sizeof(flash_device_desc), .bDescriptorType = USB_DT_DEVICE, diff --git a/include/scsi.h b/include/scsi.h index 5d63963bed0..d8f0d9c7dcd 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -173,6 +173,32 @@ enum scsi_cmd_phase { SCSIPH_STATUS, };
+struct scsi_inquiry_resp { + u8 type; + u8 flags; + u8 version; + u8 data_format; + u8 additional_len; + u8 spare[3]; + char vendor[8]; + char product[16]; + char revision[4]; +}; + +struct scsi_read_capacity_resp { + u32 last_block_addr; + u32 block_len; +}; + +struct __packed scsi_read10_req { + u8 cmd; + u8 lun_flags; + u32 lba; + u8 spare; + u16 xfer_len; + u8 spare2[3]; +}; + /** * struct scsi_plat - stores information about SCSI controller *

On 8/27/22 17:15, Simon Glass wrote:
Move these to the SCSI header file so we can access them from multiple emulators.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/usb/emul/sandbox_flash.c | 26 -------------------------- include/scsi.h | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 7b9a99c1a38..2059fc7fe42 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -57,32 +57,6 @@ struct sandbox_flash_plat { struct usb_string flash_strings[STRINGID_COUNT]; };
-struct scsi_inquiry_resp {
- u8 type;
- u8 flags;
- u8 version;
- u8 data_format;
- u8 additional_len;
- u8 spare[3];
- char vendor[8];
- char product[16];
- char revision[4];
-};
-struct scsi_read_capacity_resp {
- u32 last_block_addr;
- u32 block_len;
-};
-struct __packed scsi_read10_req {
- u8 cmd;
- u8 lun_flags;
- u32 lba;
- u8 spare;
- u16 xfer_len;
- u8 spare2[3];
-};
- static struct usb_device_descriptor flash_device_desc = { .bLength = sizeof(flash_device_desc), .bDescriptorType = USB_DT_DEVICE,
diff --git a/include/scsi.h b/include/scsi.h index 5d63963bed0..d8f0d9c7dcd 100644 --- a/include/scsi.h +++ b/include/scsi.h @@ -173,6 +173,32 @@ enum scsi_cmd_phase { SCSIPH_STATUS, };
+struct scsi_inquiry_resp {
Where is the (Sphinx style) description?
Best regards
Heinrich
- u8 type;
- u8 flags;
- u8 version;
- u8 data_format;
- u8 additional_len;
- u8 spare[3];
- char vendor[8];
- char product[16];
- char revision[4];
+};
+struct scsi_read_capacity_resp {
- u32 last_block_addr;
- u32 block_len;
+};
+struct __packed scsi_read10_req {
- u8 cmd;
- u8 lun_flags;
- u32 lba;
- u8 spare;
- u16 xfer_len;
- u8 spare2[3];
+};
- /**
- struct scsi_plat - stores information about SCSI controller

This will be needed to run unit tests, once the SCSI code is used for USB as well. Enable it for all sandbox builds.
Signed-off-by: Simon Glass sjg@chromium.org ---
configs/sandbox64_defconfig | 5 +++++ configs/sandbox_flattree_defconfig | 4 ++++ configs/sandbox_noinst_defconfig | 4 ++++ configs/sandbox_spl_defconfig | 6 +++++- configs/sandbox_vpl_defconfig | 4 ++++ 5 files changed, 22 insertions(+), 1 deletion(-)
diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index 528ed867d73..fdbb6eb4b85 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -52,6 +52,7 @@ CONFIG_CMD_OSD=y CONFIG_CMD_PCI=y CONFIG_CMD_READ=y CONFIG_CMD_REMOTEPROC=y +# CONFIG_CMD_SATA is not set CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_BOOTP_DNS2=y @@ -203,6 +204,10 @@ CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_RTC_RV8803=y +CONFIG_SCSI=y +CONFIG_SCSI_AHCI_PLAT=y +CONFIG_SYS_SCSI_MAX_SCSI_ID=8 +CONFIG_SYS_SCSI_MAX_LUN=4 CONFIG_SANDBOX_SERIAL=y CONFIG_SMEM=y CONFIG_SANDBOX_SMEM=y diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 6d62feeb08a..95ff77d8824 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -175,6 +175,10 @@ CONFIG_REMOTEPROC_SANDBOX=y CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y +CONFIG_SCSI=y +CONFIG_SCSI_AHCI_PLAT=y +CONFIG_SYS_SCSI_MAX_SCSI_ID=8 +CONFIG_SYS_SCSI_MAX_LUN=4 CONFIG_SANDBOX_SERIAL=y CONFIG_SOUND=y CONFIG_SOUND_SANDBOX=y diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index 9ee70c29c1a..dcae8fa2582 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -201,6 +201,10 @@ CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y +CONFIG_SCSI=y +CONFIG_SCSI_AHCI_PLAT=y +CONFIG_SYS_SCSI_MAX_SCSI_ID=8 +CONFIG_SYS_SCSI_MAX_LUN=4 CONFIG_SANDBOX_SERIAL=y CONFIG_SOUND=y CONFIG_SOUND_SANDBOX=y diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index fe5116d36ba..9454e942315 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -61,6 +61,7 @@ CONFIG_CMD_I2C=y CONFIG_CMD_OSD=y CONFIG_CMD_PCI=y CONFIG_CMD_REMOTEPROC=y +# CONFIG_CMD_SATA is not set CONFIG_CMD_SPI=y CONFIG_CMD_USB=y CONFIG_BOOTP_DNS2=y @@ -109,7 +110,6 @@ CONFIG_DEBUG_DEVRES=y # CONFIG_SPL_SIMPLE_BUS is not set CONFIG_ADC=y CONFIG_ADC_SANDBOX=y -CONFIG_SYS_SATA_MAX_DEVICE=2 CONFIG_AXI=y CONFIG_AXI_SANDBOX=y CONFIG_SYS_IDE_MAXBUS=1 @@ -204,6 +204,10 @@ CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y +CONFIG_SCSI=y +CONFIG_SCSI_AHCI_PLAT=y +CONFIG_SYS_SCSI_MAX_SCSI_ID=8 +CONFIG_SYS_SCSI_MAX_LUN=4 CONFIG_SANDBOX_SERIAL=y CONFIG_SOUND=y CONFIG_SOUND_SANDBOX=y diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index 0d946b4ad77..f5ef760b5d5 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -210,6 +210,10 @@ CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y CONFIG_TPL_DM_RTC=y +CONFIG_SCSI=y +CONFIG_SCSI_AHCI_PLAT=y +CONFIG_SYS_SCSI_MAX_SCSI_ID=8 +CONFIG_SYS_SCSI_MAX_LUN=4 CONFIG_SANDBOX_SERIAL=y CONFIG_SOUND=y CONFIG_SOUND_SANDBOX=y

Move this code into the emulator file so it can be used by multiple drivers.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/scsi/Makefile | 1 + drivers/scsi/scsi_emul.c | 74 +++++++++++++++++++++++++++ drivers/usb/emul/sandbox_flash.c | 87 ++++---------------------------- include/scsi_emul.h | 24 +++++++++ 4 files changed, 109 insertions(+), 77 deletions(-) create mode 100644 drivers/scsi/scsi_emul.c
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 25194eeec11..d1b40c61401 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -17,4 +17,5 @@ endif
ifdef CONFIG_SCSI obj-$(CONFIG_SANDBOX) += sandbox_scsi.o +obj-$(CONFIG_SANDBOX) += scsi_emul.o endif diff --git a/drivers/scsi/scsi_emul.c b/drivers/scsi/scsi_emul.c new file mode 100644 index 00000000000..5ba364bdac7 --- /dev/null +++ b/drivers/scsi/scsi_emul.c @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Emulation of enough SCSI commands to find and read from a unit + * + * Copyright 2022 Google LLC + * Written by Simon Glass sjg@chromium.org + * + * implementation of SCSI functions required so that CONFIG_SCSI can be enabled + * for sandbox. + */ + +#define LOG_CATEGORY UCLASS_SCSI + +#include <common.h> +#include <dm.h> +#include <log.h> +#include <scsi.h> +#include <scsi_emul.h> + +int sb_scsi_emul_command(struct scsi_emul_info *info, + const struct scsi_cmd *req, int len) +{ + int ret = 0; + + info->buff_used = 0; + log_debug("emul %x\n", *req->cmd); + switch (*req->cmd) { + case SCSI_INQUIRY: { + struct scsi_inquiry_resp *resp = (void *)info->buff; + + info->alloc_len = req->cmd[4]; + memset(resp, '\0', sizeof(*resp)); + resp->data_format = 1; + resp->additional_len = 0x1f; + strncpy(resp->vendor, info->vendor, sizeof(resp->vendor)); + strncpy(resp->product, info->product, sizeof(resp->product)); + strncpy(resp->revision, "1.0", sizeof(resp->revision)); + info->buff_used = sizeof(*resp); + break; + } + case SCSI_TST_U_RDY: + break; + case SCSI_RD_CAPAC: { + struct scsi_read_capacity_resp *resp = (void *)info->buff; + uint blocks; + + if (info->file_size) + blocks = info->file_size / info->block_size - 1; + else + blocks = 0; + resp->last_block_addr = cpu_to_be32(blocks); + resp->block_len = cpu_to_be32(info->block_size); + info->buff_used = sizeof(*resp); + break; + } + case SCSI_READ10: { + const struct scsi_read10_req *read_req = (void *)req; + + info->seek_block = be32_to_cpu(read_req->lba); + info->read_len = be16_to_cpu(read_req->xfer_len); + info->buff_used = info->read_len * info->block_size; + ret = SCSI_EMUL_DO_READ; + break; + } + default: + debug("Command not supported: %x\n", req->cmd[0]); + ret = -EPROTONOSUPPORT; + } + if (ret >= 0) + info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; + log_debug(" - done %x: ret=%d\n", *req->cmd, ret); + + return ret; +} diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 2059fc7fe42..2589c708d88 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -180,97 +180,30 @@ static void setup_response(struct sandbox_flash_priv *priv) csw->bCSWStatus = CSWSTATUS_GOOD; }
-/** - * handle_read() - prepare for reading data from the backing file - * - * This seeks to the correct file position and sets info->buff_used to the - * correct size. - * - * @priv: Private information - * @lba: Start block to read from - * @transfer_length: Number of blocks to read - * @return 0 if OK, -EIO on failure - */ -static int handle_read(struct sandbox_flash_priv *priv, ulong lba, - ulong transfer_len) -{ - struct scsi_emul_info *info = &priv->eminfo; - - debug("%s: lba=%lx, transfer_len=%lx\n", __func__, lba, transfer_len); - info->read_len = transfer_len; - if (priv->fd != -1) { - os_lseek(priv->fd, lba * info->block_size, OS_SEEK_SET); - info->buff_used = transfer_len * info->block_size; - return 0; - } - - return -EIO; -} - -static int handle_ufi_command(struct sandbox_flash_plat *plat, - struct sandbox_flash_priv *priv, const void *buff, +static int handle_ufi_command(struct sandbox_flash_priv *priv, const void *buff, int len) { struct scsi_emul_info *info = &priv->eminfo; const struct scsi_cmd *req = buff; + int ret;
- info->buff_used = 0; - switch (*req->cmd) { - case SCSI_INQUIRY: { - struct scsi_inquiry_resp *resp = (void *)info->buff; - - info->alloc_len = req->cmd[4]; - memset(resp, '\0', sizeof(*resp)); - resp->data_format = 1; - resp->additional_len = 0x1f; - strncpy(resp->vendor, info->vendor, sizeof(resp->vendor)); - strncpy(resp->product, info->product, sizeof(resp->product)); - strncpy(resp->revision, "1.0", sizeof(resp->revision)); - info->buff_used = sizeof(*resp); - setup_response(priv); - break; - } - case SCSI_TST_U_RDY: + ret = sb_scsi_emul_command(info, req, len); + if (!ret) { setup_response(priv); - break; - case SCSI_RD_CAPAC: { - struct scsi_read_capacity_resp *resp = (void *)info->buff; - uint blocks; - - if (info->file_size) - blocks = info->file_size / info->block_size - 1; - else - blocks = 0; - resp->last_block_addr = cpu_to_be32(blocks); - resp->block_len = cpu_to_be32(info->block_size); - info->buff_used = sizeof(*resp); + } else if (ret == SCSI_EMUL_DO_READ && priv->fd != -1) { + os_lseek(priv->fd, info->seek_block * info->block_size, + OS_SEEK_SET); setup_response(priv); - break; + } else { + setup_fail_response(priv); } - case SCSI_READ10: { - struct scsi_read10_req *req = (void *)buff;
- if (!handle_read(priv, be32_to_cpu(req->lba), - be16_to_cpu(req->xfer_len))) - setup_response(priv); - else - setup_fail_response(priv); - - break; - } - default: - debug("Command not supported: %x\n", req->cmd[0]); - return -EPROTONOSUPPORT; - } - - info->phase = info->transfer_len ? SCSIPH_DATA : SCSIPH_STATUS; return 0; }
static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, unsigned long pipe, void *buff, int len) { - struct sandbox_flash_plat *plat = dev_get_plat(dev); struct sandbox_flash_priv *priv = dev_get_priv(dev); struct scsi_emul_info *info = &priv->eminfo; int ep = usb_pipeendpoint(pipe); @@ -294,7 +227,7 @@ static int sandbox_flash_bulk(struct udevice *dev, struct usb_device *udev, goto err; info->transfer_len = cbw->dCBWDataTransferLength; priv->tag = cbw->dCBWTag; - return handle_ufi_command(plat, priv, cbw->CBWCDB, + return handle_ufi_command(priv, cbw->CBWCDB, cbw->bCDBLength); case SCSIPH_DATA: debug("data out\n"); diff --git a/include/scsi_emul.h b/include/scsi_emul.h index 3c52398e3ff..a55311d59bc 100644 --- a/include/scsi_emul.h +++ b/include/scsi_emul.h @@ -19,6 +19,7 @@ * @product: Product name * @block_size: Block size of device in bytes (normally 512) * @file_size: Size of the backing file for this emulator, in bytes + * @seek_block: Seek position for file (block number) * * @phase: Current SCSI phase * @buff_used: Number of bytes ready to transfer back to host @@ -34,13 +35,36 @@ struct scsi_emul_info { const char *product; int block_size; loff_t file_size; + int seek_block;
/* state maintained by the emulator: */ enum scsi_cmd_phase phase; int buff_used; int read_len; + uint seek_pos; int alloc_len; uint transfer_len; };
+/* Indicates that a read is being started */ +#define SCSI_EMUL_DO_READ 1 + +/** + * sb_scsi_emul_command() - Process a SCSI command + * + * This sets up the response in info->buff and updates various other values + * in info. + * + * If SCSI_EMUL_DO_READ is returned then the caller should set up so that the + * backing file can be read, or return an error status if there is no file. + * + * @info: Emulation information + * @req: Request to process + * @len: Length of request in bytes + * @return SCSI_EMUL_DO_READ if a read has started, 0 if some other operation + * has start, -ve if there was an error + */ +int sb_scsi_emul_command(struct scsi_emul_info *info, + const struct scsi_cmd *req, int len); + #endif

At present sandbox is producing a warning about SCSI migration. Drop the legacy code and replace it with a new implementation.
Also drop the SATA command, which does not work with driver model.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/Kconfig | 1 - configs/sandbox64_defconfig | 1 + configs/sandbox_defconfig | 1 + configs/sandbox_flattree_defconfig | 1 + configs/sandbox_noinst_defconfig | 1 + configs/sandbox_spl_defconfig | 1 + configs/sandbox_vpl_defconfig | 1 + drivers/scsi/sandbox_scsi.c | 132 ++++++++++++++++++++++++++++- 8 files changed, 135 insertions(+), 4 deletions(-)
diff --git a/arch/Kconfig b/arch/Kconfig index 994fd3b7f86..1ffd77c0f4f 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -166,7 +166,6 @@ config SANDBOX imply CMD_IO imply CMD_IOTRACE imply CMD_LZMADEC - imply CMD_SATA imply CMD_SF imply CMD_SF_TEST imply CRC32_VERIFY diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig index fdbb6eb4b85..deefc99d8d1 100644 --- a/configs/sandbox64_defconfig +++ b/configs/sandbox64_defconfig @@ -205,6 +205,7 @@ CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_RTC_RV8803=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 3e9bb9e628d..c7026da1bbf 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -263,6 +263,7 @@ CONFIG_RESET_SCMI=y CONFIG_DM_RTC=y CONFIG_RTC_RV8803=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig index 95ff77d8824..226a36f0fe9 100644 --- a/configs/sandbox_flattree_defconfig +++ b/configs/sandbox_flattree_defconfig @@ -176,6 +176,7 @@ CONFIG_DM_RESET=y CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/configs/sandbox_noinst_defconfig b/configs/sandbox_noinst_defconfig index dcae8fa2582..e4bf05df1d8 100644 --- a/configs/sandbox_noinst_defconfig +++ b/configs/sandbox_noinst_defconfig @@ -202,6 +202,7 @@ CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig index 9454e942315..fcaee771055 100644 --- a/configs/sandbox_spl_defconfig +++ b/configs/sandbox_spl_defconfig @@ -205,6 +205,7 @@ CONFIG_SANDBOX_RESET=y CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/configs/sandbox_vpl_defconfig b/configs/sandbox_vpl_defconfig index f5ef760b5d5..593e72aa6a7 100644 --- a/configs/sandbox_vpl_defconfig +++ b/configs/sandbox_vpl_defconfig @@ -211,6 +211,7 @@ CONFIG_DM_RTC=y CONFIG_SPL_DM_RTC=y CONFIG_TPL_DM_RTC=y CONFIG_SCSI=y +CONFIG_DM_SCSI=y CONFIG_SCSI_AHCI_PLAT=y CONFIG_SYS_SCSI_MAX_SCSI_ID=8 CONFIG_SYS_SCSI_MAX_LUN=4 diff --git a/drivers/scsi/sandbox_scsi.c b/drivers/scsi/sandbox_scsi.c index 39b969a4b2f..a7ac33cb1c4 100644 --- a/drivers/scsi/sandbox_scsi.c +++ b/drivers/scsi/sandbox_scsi.c @@ -7,19 +7,145 @@ * that CONFIG_SCSI can be enabled for sandbox. */
+#define LOG_CATEGORY UCLASS_SCSI + #include <common.h> +#include <dm.h> +#include <os.h> +#include <malloc.h> #include <scsi.h> +#include <scsi_emul.h> + +enum { + SANDBOX_SCSI_BLOCK_LEN = 512, + SANDBOX_SCSI_BUF_SIZE = 512, +}; + +/** + * struct sandbox_scsi_priv + * + * @eminfo: emulator state + * @pathanme: Path to the backing file, e.g. 'scsi.img' + * @fd: File descriptor of backing file + */ +struct sandbox_scsi_priv { + struct scsi_emul_info eminfo; + const char *pathname; + int fd; +};
-int scsi_bus_reset(struct udevice *dev) +static int sandbox_scsi_exec(struct udevice *dev, struct scsi_cmd *req) { + struct sandbox_scsi_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; + int ret; + + if (req->lun || req->target) + return -EIO; + ret = sb_scsi_emul_command(info, req, req->cmdlen); + if (ret < 0) { + log_debug("SCSI command 0x%02x ret errno %d\n", req->cmd[0], + ret); + return ret; + } else if (ret == SCSI_EMUL_DO_READ && priv->fd != -1) { + long bytes_read; + + log_debug("read %x %x\n", info->seek_block, info->read_len); + os_lseek(priv->fd, info->seek_block * info->block_size, + OS_SEEK_SET); + bytes_read = os_read(priv->fd, req->pdata, info->buff_used); + if (bytes_read < 0) + return bytes_read; + if (bytes_read != info->buff_used) + return -EIO; + } else if (!ret) { + req->pdata = info->buff; + info->phase = SCSIPH_STATUS; + log_debug("sending buf\n"); + } else { + log_debug("error\n"); + return -EIO; + } + return 0; }
-void scsi_init(void) +static int sandbox_scsi_bus_reset(struct udevice *dev) { + /* Not implemented */ + + return 0; }
-int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb) +static int sandbox_scsi_of_to_plat(struct udevice *dev) { + struct sandbox_scsi_priv *priv = dev_get_priv(dev); + + priv->pathname = dev_read_string(dev, "sandbox,filepath"); + return 0; } + +static int sandbox_scsi_probe(struct udevice *dev) +{ + struct scsi_plat *scsi_plat = dev_get_uclass_plat(dev); + struct sandbox_scsi_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; + int ret; + + scsi_plat->max_id = 2; + scsi_plat->max_lun = 3; + scsi_plat->max_bytes_per_req = 1 << 20; + + info->vendor = "SANDBOX"; + info->product = "FAKE DISK"; + info->buff = malloc(SANDBOX_SCSI_BUF_SIZE); + if (!info->buff) + return log_ret(-ENOMEM); + info->block_size = SANDBOX_SCSI_BLOCK_LEN; + + if (priv->pathname) { + priv->fd = os_open(priv->pathname, OS_O_RDONLY); + if (priv->fd != -1) { + ret = os_get_filesize(priv->pathname, &info->file_size); + if (ret) + return log_msg_ret("sz", ret); + } + } else { + priv->fd = -1; + } + log_debug("filename: %s, fd %d\n", priv->pathname, priv->fd); + + return 0; +} + +static int sandbox_scsi_remove(struct udevice *dev) +{ + struct sandbox_scsi_priv *priv = dev_get_priv(dev); + struct scsi_emul_info *info = &priv->eminfo; + + free(info->buff); + + return 0; +} + +struct scsi_ops sandbox_scsi_ops = { + .exec = sandbox_scsi_exec, + .bus_reset = sandbox_scsi_bus_reset, +}; + +static const struct udevice_id sanbox_scsi_ids[] = { + { .compatible = "sandbox,scsi" }, + { } +}; + +U_BOOT_DRIVER(sandbox_scsi) = { + .name = "sandbox_scsi", + .id = UCLASS_SCSI, + .ops = &sandbox_scsi_ops, + .of_match = sanbox_scsi_ids, + .of_to_plat = sandbox_scsi_of_to_plat, + .probe = sandbox_scsi_probe, + .remove = sandbox_scsi_remove, + .priv_auto = sizeof(struct sandbox_scsi_priv), +};

Add a simple uclass test for SCSI. It reads the partition table from a disk image and checks that it looks correct.
Signed-off-by: Simon Glass sjg@chromium.org ---
arch/sandbox/dts/sandbox.dtsi | 4 ++++ arch/sandbox/dts/test.dts | 5 +++++ test/dm/Makefile | 1 + test/dm/scsi.c | 39 +++++++++++++++++++++++++++++++++++ test/py/tests/test_ut.py | 9 ++++++++ 5 files changed, 58 insertions(+) create mode 100644 test/dm/scsi.c
diff --git a/arch/sandbox/dts/sandbox.dtsi b/arch/sandbox/dts/sandbox.dtsi index 56e6b38bfa7..de7a218f457 100644 --- a/arch/sandbox/dts/sandbox.dtsi +++ b/arch/sandbox/dts/sandbox.dtsi @@ -245,6 +245,10 @@ compatible = "sandbox,sandbox-rng"; };
+ scsi { + compatible = "sandbox,scsi"; + }; + sound { compatible = "sandbox,sound"; cpu { diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts index 2761588f0da..66391f7135b 100644 --- a/arch/sandbox/dts/test.dts +++ b/arch/sandbox/dts/test.dts @@ -1156,6 +1156,11 @@ backlight = <&backlight 0 100>; };
+ scsi { + compatible = "sandbox,scsi"; + sandbox,filepath = "scsi.img"; + }; + smem@0 { compatible = "sandbox,smem"; }; diff --git a/test/dm/Makefile b/test/dm/Makefile index 52fe178a828..cfcd13fe4d4 100644 --- a/test/dm/Makefile +++ b/test/dm/Makefile @@ -91,6 +91,7 @@ obj-$(CONFIG_DM_REGULATOR) += regulator.o obj-$(CONFIG_DM_RNG) += rng.o obj-$(CONFIG_DM_RTC) += rtc.o obj-$(CONFIG_SCMI_FIRMWARE) += scmi.o +obj-$(CONFIG_SCSI) += scsi.o obj-$(CONFIG_DM_SERIAL) += serial.o obj-$(CONFIG_DM_SPI_FLASH) += sf.o obj-$(CONFIG_SIMPLE_BUS) += simple-bus.o diff --git a/test/dm/scsi.c b/test/dm/scsi.c new file mode 100644 index 00000000000..380cfc88bab --- /dev/null +++ b/test/dm/scsi.c @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2015 Google, Inc + */ + +#include <common.h> +#include <dm.h> +#include <part.h> +#include <scsi.h> +#include <dm/test.h> +#include <test/test.h> +#include <test/ut.h> + +/* Test that sandbox SCSI works correctly */ +static int dm_test_scsi_base(struct unit_test_state *uts) +{ + const struct disk_partition *info; + const struct disk_part *part; + struct udevice *dev; + + ut_assertok(scsi_scan(false)); + + /* + * We expect some sort of partition on the disk image, created by + * test_ut_dm_init() + */ + ut_assertok(uclass_first_device_err(UCLASS_PARTITION, &dev)); + + part = dev_get_uclass_plat(dev); + ut_asserteq(1, part->partnum); + + info = &part->gpt_part_info; + ut_asserteq_str("sda1", info->name); + ut_asserteq_str("U-Boot", info->type); + ut_asserteq(0x83 /* linux */, info->sys_ind); + + return 0; +} +DM_TEST(dm_test_scsi_base, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py index 35fb393c1ff..9d423903736 100644 --- a/test/py/tests/test_ut.py +++ b/test/py/tests/test_ut.py @@ -114,6 +114,15 @@ def test_ut_dm_init(u_boot_console): with open(fn, 'wb') as fh: fh.write(data)
+ # Create a file with a single partition + fn = u_boot_console.config.source_dir + '/scsi.img' + if not os.path.exists(fn): + data = b'\x00' * (2 * 1024 * 1024) + with open(fn, 'wb') as fh: + fh.write(data) + u_boot_utils.run_and_log( + u_boot_console, f'sfdisk {fn}', stdin=b'type=83') + @pytest.mark.buildconfigspec('cmd_bootflow') def test_ut_dm_init_bootstd(u_boot_console): """Initialise data for bootflow tests"""
participants (2)
-
Heinrich Schuchardt
-
Simon Glass