Module Name: src Committed By: bouyer Date: Sat Sep 5 12:57:00 UTC 2009
Modified Files: src/distrib/utils/sysinst [netbsd-5]: disks.c Log Message: Pull up following revision(s) (requested by jmcneill in ticket #924): distrib/utils/sysinst/disks.c: revision 1.106 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@ To generate a diff of this commit: cvs rdiff -u -r1.100.2.3 -r1.100.2.4 src/distrib/utils/sysinst/disks.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/utils/sysinst/disks.c diff -u src/distrib/utils/sysinst/disks.c:1.100.2.3 src/distrib/utils/sysinst/disks.c:1.100.2.4 --- src/distrib/utils/sysinst/disks.c:1.100.2.3 Mon May 18 19:35:14 2009 +++ src/distrib/utils/sysinst/disks.c Sat Sep 5 12:57:00 2009 @@ -1,4 +1,4 @@ -/* $NetBSD: disks.c,v 1.100.2.3 2009/05/18 19:35:14 bouyer Exp $ */ +/* $NetBSD: disks.c,v 1.100.2.4 2009/09/05 12:57:00 bouyer 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;