Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/distrib/utils/sysinst PR# install/41925: sysinst find_disks(...



details:   https://anonhg.NetBSD.org/src/rev/cc9110505008
branches:  trunk
changeset: 746931:cc9110505008
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Aug 23 18:43:33 2009 +0000

description:
PR# install/41925: sysinst find_disks() should display more than just
                   the device name

Try ATA/SCSI identify commands and when successful, use the model information
along with the disk size when creating the 'Available disks' menu.

Instead of having a list of disks (wd0, wd1, sd0) the menu now looks like:

  Available disks

 >a: wd0 (977M, SanDisk SDCFB-1024)
  b: wd1 (233G, FUJITSU MHY2250BH)
  c: sd0 (246M, LEXAR JUMPDRIVE ELITE)

ok martin@

diffstat:

 distrib/utils/sysinst/disks.c |  221 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 218 insertions(+), 3 deletions(-)

diffs (267 lines):

diff -r 22138ed91776 -r cc9110505008 distrib/utils/sysinst/disks.c
--- a/distrib/utils/sysinst/disks.c     Sun Aug 23 16:21:55 2009 +0000
+++ b/distrib/utils/sysinst/disks.c     Sun Aug 23 18:43:33 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: disks.c,v 1.105 2009/05/14 16:23:38 sborrill Exp $ */
+/*     $NetBSD: disks.c,v 1.106 2009/08/23 18:43:33 jmcneill Exp $ */
 
 /*
  * Copyright 1997 Piermont Information Systems Inc.
@@ -56,6 +56,12 @@
 #include <sys/disklabel.h>
 #undef static
 
+#include <dev/scsipi/scsipi_all.h>
+#include <sys/scsiio.h>
+
+#include <dev/ata/atareg.h>
+#include <sys/ataio.h>
+
 #include "defs.h"
 #include "md.h"
 #include "msg_defs.h"
@@ -66,6 +72,7 @@
 #define MAX_DISKS 15
 struct disk_desc {
        char    dd_name[SSTRSIZE];
+       char    dd_descr[70];
        uint    dd_no_mbr;
        uint    dd_cyl;
        uint    dd_head;
@@ -88,6 +95,213 @@
 
 static const char *disk_names[] = { DISK_NAMES, "vnd", NULL };
 
+/* from src/sbin/atactl/atactl.c
+ * extract_string: copy a block of bytes out of ataparams and make
+ * a proper string out of it, truncating trailing spaces and preserving
+ * strict typing. And also, not doing unaligned accesses.
+ */
+static void
+ata_extract_string(char *buf, size_t bufmax,
+                  uint8_t *bytes, unsigned numbytes,
+                  int needswap)
+{
+       unsigned i;
+       size_t j;
+       unsigned char ch1, ch2;
+
+       for (i = 0, j = 0; i < numbytes; i += 2) {
+               ch1 = bytes[i];
+               ch2 = bytes[i+1];
+               if (needswap && j < bufmax-1) {
+                       buf[j++] = ch2;
+               }
+               if (j < bufmax-1) {
+                       buf[j++] = ch1;
+               }
+               if (!needswap && j < bufmax-1) {
+                       buf[j++] = ch2;
+               }
+       }
+       while (j > 0 && buf[j-1] == ' ') {
+               j--;
+       }
+       buf[j] = '\0';
+}
+
+/*
+ * from src/sbin/scsictl/scsi_subr.c
+ */
+#define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
+
+static void
+scsi_strvis(char *sdst, size_t dlen, const char *ssrc, size_t slen)
+{
+       u_char *dst = (u_char *)sdst;
+       const u_char *src = (const u_char *)ssrc;
+
+       /* Trim leading and trailing blanks and NULs. */
+       while (slen > 0 && STRVIS_ISWHITE(src[0]))
+               ++src, --slen;
+       while (slen > 0 && STRVIS_ISWHITE(src[slen - 1]))
+               --slen;
+
+       while (slen > 0) {
+               if (*src < 0x20 || *src >= 0x80) {
+                       /* non-printable characters */
+                       dlen -= 4;
+                       if (dlen < 1)
+                               break;
+                       *dst++ = '\\';
+                       *dst++ = ((*src & 0300) >> 6) + '0';
+                       *dst++ = ((*src & 0070) >> 3) + '0';
+                       *dst++ = ((*src & 0007) >> 0) + '0';
+               } else if (*src == '\\') {
+                       /* quote characters */
+                       dlen -= 2;
+                       if (dlen < 1)
+                               break;
+                       *dst++ = '\\';
+                       *dst++ = '\\';
+               } else {
+                       /* normal characters */
+                       if (--dlen < 1)
+                               break;
+                       *dst++ = *src;
+               }
+               ++src, --slen;
+       }
+
+       *dst++ = 0;
+}
+
+
+static int
+get_descr_scsi(struct disk_desc *dd, int fd)
+{
+       struct scsipi_inquiry_data inqbuf;
+       struct scsipi_inquiry cmd;
+       scsireq_t req;
+        /* x4 in case every character is escaped, +1 for NUL. */
+       char vendor[(sizeof(inqbuf.vendor) * 4) + 1],
+            product[(sizeof(inqbuf.product) * 4) + 1],
+            revision[(sizeof(inqbuf.revision) * 4) + 1];
+       char size[5];
+       int error;
+
+       memset(&inqbuf, 0, sizeof(inqbuf));
+       memset(&cmd, 0, sizeof(cmd));
+       memset(&req, 0, sizeof(req));
+
+       cmd.opcode = INQUIRY;
+       cmd.length = sizeof(inqbuf);
+       memcpy(req.cmd, &cmd, sizeof(cmd));
+       req.cmdlen = sizeof(cmd);
+       req.databuf = &inqbuf;
+       req.datalen = sizeof(inqbuf);
+       req.timeout = 10000;
+       req.flags = SCCMD_READ;
+       req.senselen = SENSEBUFLEN;
+
+       error = ioctl(fd, SCIOCCOMMAND, &req);
+       if (error == -1 || req.retsts != SCCMD_OK)
+               return 0;
+
+       scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor,
+           sizeof(inqbuf.vendor));
+       scsi_strvis(product, sizeof(product), inqbuf.product,
+           sizeof(inqbuf.product));
+       scsi_strvis(revision, sizeof(revision), inqbuf.revision,
+           sizeof(inqbuf.revision));
+
+       humanize_number(size, sizeof(size),
+           (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec,
+           "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+       
+       snprintf(dd->dd_descr, sizeof(dd->dd_descr),
+           "%s (%s, %s %s)",
+           dd->dd_name, size, vendor, product);
+
+       return 1;
+}
+
+static int
+get_descr_ata(struct disk_desc *dd, int fd)
+{
+       struct atareq req;
+       static union {
+               unsigned char inbuf[DEV_BSIZE];
+               struct ataparams inqbuf;
+       } inbuf;
+       struct ataparams *inqbuf = &inbuf.inqbuf;
+       char model[sizeof(inqbuf->atap_model)+1];
+       char size[5];
+       int error, needswap = 0;
+
+       memset(&inbuf, 0, sizeof(inbuf));
+       memset(&req, 0, sizeof(req));
+
+       req.flags = ATACMD_READ;
+       req.command = WDCC_IDENTIFY;
+       req.databuf = (void *)&inbuf;
+       req.datalen = sizeof(inbuf);
+       req.timeout = 1000;
+
+       error = ioctl(fd, ATAIOCCOMMAND, &req);
+       if (error == -1 || req.retsts != ATACMD_OK)
+               return 0;
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+       /*
+        * On little endian machines, we need to shuffle the string
+        * byte order.  However, we don't have to do this for NEC or
+        * Mitsumi ATAPI devices
+        */
+
+       if (!((inqbuf->atap_config & WDC_CFG_ATAPI_MASK) == WDC_CFG_ATAPI &&
+             ((inqbuf->atap_model[0] == 'N' &&
+                 inqbuf->atap_model[1] == 'E') ||
+              (inqbuf->atap_model[0] == 'F' &&
+                 inqbuf->atap_model[1] == 'X')))) {
+               needswap = 1;
+       }
+#endif
+
+       ata_extract_string(model, sizeof(model),
+           inqbuf->atap_model, sizeof(inqbuf->atap_model), needswap);
+       humanize_number(size, sizeof(size),
+           (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec,
+           "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL);
+       
+       snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s, %s)",
+           dd->dd_name, size, model);
+
+       return 1;
+}
+
+static void
+get_descr(struct disk_desc *dd)
+{
+       char diskpath[MAXPATHLEN];
+       int fd = -1;
+
+       fd = opendisk(dd->dd_name, O_RDONLY, diskpath, sizeof(diskpath), 0);
+       if (fd < 0)
+               goto done;
+
+       /* try ATA */
+       if (get_descr_ata(dd, fd))
+               goto done;
+       /* try SCSI */
+       if (get_descr_scsi(dd, fd))
+               goto done;
+
+done:
+       if (fd >= 0)
+               close(fd);
+       if (strlen(dd->dd_descr) == 0)
+               strcpy(dd->dd_descr, dd->dd_name);
+}
+
 static int
 get_disks(struct disk_desc *dd)
 {
@@ -122,6 +336,7 @@
                        dd->dd_sec = l.d_nsectors;
                        dd->dd_secsize = l.d_secsize;
                        dd->dd_totsec = l.d_secperunit;
+                       get_descr(dd);
                        dd++;
                        numdisks++;
                        if (numdisks >= MAX_DISKS)
@@ -168,12 +383,12 @@
 
        if (numdisks == 1) {
                /* One disk found! */
-               msg_display(MSG_onedisk, disks[0].dd_name, doingwhat);
+               msg_display(MSG_onedisk, disks[0].dd_descr, doingwhat);
                process_menu(MENU_ok, NULL);
        } else {
                /* Multiple disks found! */
                for (i = 0; i < numdisks; i++) {
-                       dsk_menu[i].opt_name = disks[i].dd_name;
+                       dsk_menu[i].opt_name = disks[i].dd_descr;
                        dsk_menu[i].opt_menu = OPT_NOMENU;
                        dsk_menu[i].opt_flags = OPT_EXIT;
                        dsk_menu[i].opt_action = set_dsk_select;



Home | Main Index | Thread Index | Old Index