> Date: Sun, 1 May 2016 23:21:18 +0200 (CEST)
> From: Mark Kettenis <[email protected]>
>
> Diff below provides a bit more meaningful information in the SCSI
> INQUIRY emulation. It decodes the JDEC manufacturer ID code and
> provides the product string and revision number as read from the card.
>
> For example:
>
> scsibus1 at sdmmc2: 2 targets, initiator 0
> sd0 at scsibus1 targ 1 lun 0: <Sandisk, SA04G, 0006> SCSI2 0/direct fixed
> sd0: 3768MB, 512 bytes/sector, 7716864 sectors
> scsibus2 at sdmmc0: 2 targets, initiator 0
> sd1 at scsibus2 targ 1 lun 0: <Kingston, S10032, 0000> SCSI2 0/direct fixed
> sd1: 29184MB, 512 bytes/sector, 59768832 sectors
>
> where sd0 is an SD card and sd1 is the eMMC soldered onto the board of
> the machine.
>
> Note that the strncpy here is safe. The strings in the scsi inquiry
> page don't have to be nul-terminated.
Theo isn't to thrilled about the use of strncpy(9), which might be
removed in the future.
The diff below uses strlcpy(9) and memcpy(9) in a way that should be
fairly easy to audit.
As a bonus it converts some bzero/bcopy calls into memset/memcpy.
Thoughts?
Index: sdmmc_scsi.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_scsi.c,v
retrieving revision 1.35
diff -u -p -r1.35 sdmmc_scsi.c
--- sdmmc_scsi.c 14 Mar 2015 03:38:49 -0000 1.35
+++ sdmmc_scsi.c 1 May 2016 22:31:27 -0000
@@ -376,8 +376,14 @@ void
sdmmc_inquiry(struct scsi_xfer *xs)
{
struct scsi_link *link = xs->sc_link;
+ struct sdmmc_softc *sc = link->adapter_softc;
+ struct sdmmc_scsi_softc *scbus = sc->sc_scsibus;
+ struct sdmmc_scsi_target *tgt = &scbus->sc_tgt[link->target];
struct scsi_inquiry_data inq;
struct scsi_inquiry *cdb = (struct scsi_inquiry *)xs->cmd;
+ char vendor[sizeof(inq.vendor) + 1];
+ char product[sizeof(inq.product) + 1];
+ char revision[sizeof(inq.revision) + 1];
if (xs->cmdlen != sizeof(*cdb)) {
xs->error = XS_DRIVER_STUFFUP;
@@ -389,17 +395,43 @@ sdmmc_inquiry(struct scsi_xfer *xs)
goto done;
}
- bzero(&inq, sizeof inq);
+ memset(vendor, 0, sizeof(vendor));
+ memset(product, 0, sizeof(product));
+ memset(revision, 0, sizeof(revision));
+ switch (tgt->card->cid.mid) {
+ case 0x02:
+ case 0x45:
+ strlcpy(vendor, "Sandisk", sizeof(vendor));
+ break;
+ case 0x11:
+ strlcpy(vendor, "Toshiba", sizeof(vendor));
+ break;
+ case 0x13:
+ strlcpy(vendor, "Micron", sizeof(vendor));
+ break;
+ case 0x15:
+ strlcpy(vendor, "Samsung", sizeof(vendor));
+ break;
+ case 0x70:
+ strlcpy(vendor, "Kingston", sizeof(vendor));
+ break;
+ default:
+ strlcpy(vendor, "SD/MMC", sizeof(vendor));
+ break;
+ }
+ strlcpy(product, tgt->card->cid.pnm, sizeof(product));
+ snprintf(revision, sizeof(revision), "%04X", tgt->card->cid.rev);
+
+ memset(&inq, 0, sizeof inq);
inq.device = T_DIRECT;
inq.version = 2;
inq.response_format = 2;
inq.additional_length = 32;
- strlcpy(inq.vendor, "SD/MMC ", sizeof(inq.vendor));
- snprintf(inq.product, sizeof(inq.product),
- "Drive #%02d", link->target);
- strlcpy(inq.revision, " ", sizeof(inq.revision));
+ memcpy(inq.vendor, vendor, sizeof(inq.vendor));
+ memcpy(inq.product, product, sizeof(inq.product));
+ memcpy(inq.revision, revision, sizeof(inq.revision));
- bcopy(&inq, xs->data, MIN(xs->datalen, sizeof(inq)));
+ memcpy(xs->data, &inq, MIN(xs->datalen, sizeof(inq)));
done:
scsi_done(xs);