fwdownload.c revision 298858
1254721Semaste/*- 2254721Semaste * Copyright (c) 2011 Sandvine Incorporated. All rights reserved. 3254721Semaste * Copyright (c) 2002-2011 Andre Albsmeier <andre@albsmeier.net> 4254721Semaste * All rights reserved. 5254721Semaste * 6254721Semaste * Redistribution and use in source and binary forms, with or without 7254721Semaste * modification, are permitted provided that the following conditions 8254721Semaste * are met: 9254721Semaste * 1. Redistributions of source code must retain the above copyright 10254721Semaste * notice, this list of conditions and the following disclaimer, 11254721Semaste * without modification, immediately at the beginning of the file. 12254721Semaste * 2. Redistributions in binary form must reproduce the above copyright 13254721Semaste * notice, this list of conditions and the following disclaimer in the 14254721Semaste * documentation and/or other materials provided with the distribution. 15254721Semaste * 16254721Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17254721Semaste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18254721Semaste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19254721Semaste * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20254721Semaste * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21254721Semaste * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22254721Semaste * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23254721Semaste * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24254721Semaste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25254721Semaste * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26254721Semaste */ 27254721Semaste 28254721Semaste/* 29254721Semaste * This software is derived from Andre Albsmeier's fwprog.c which contained 30254721Semaste * the following note: 31269024Semaste * 32269024Semaste * Many thanks goes to Marc Frajola <marc@terasolutions.com> from 33254721Semaste * TeraSolutions for the initial idea and his programme for upgrading 34254721Semaste * the firmware of I*M DDYS drives. 35254721Semaste */ 36254721Semaste 37254721Semaste/* 38254721Semaste * BEWARE: 39254721Semaste * 40254721Semaste * The fact that you see your favorite vendor listed below does not 41254721Semaste * imply that your equipment won't break when you use this software 42254721Semaste * with it. It only means that the firmware of at least one device type 43254721Semaste * of each vendor listed has been programmed successfully using this code. 44254721Semaste * 45254721Semaste * The -s option simulates a download but does nothing apart from that. 46254721Semaste * It can be used to check what chunk sizes would have been used with the 47269024Semaste * specified device. 48254721Semaste */ 49263363Semaste 50254721Semaste#include <sys/cdefs.h> 51254721Semaste__FBSDID("$FreeBSD: head/sbin/camcontrol/fwdownload.c 298858 2016-04-30 19:04:59Z pfg $"); 52254721Semaste 53254721Semaste#include <sys/types.h> 54254721Semaste#include <sys/stat.h> 55254721Semaste 56254721Semaste#include <err.h> 57254721Semaste#include <fcntl.h> 58254721Semaste#include <stdio.h> 59254721Semaste#include <stdlib.h> 60254721Semaste#include <string.h> 61254721Semaste#include <unistd.h> 62254721Semaste 63254721Semaste#include <cam/scsi/scsi_all.h> 64254721Semaste#include <cam/scsi/scsi_message.h> 65254721Semaste#include <camlib.h> 66254721Semaste 67254721Semaste#include "progress.h" 68254721Semaste 69254721Semaste#include "camcontrol.h" 70254721Semaste 71254721Semaste#define WB_TIMEOUT 50000 /* 50 seconds */ 72254721Semaste 73254721Semastetypedef enum { 74254721Semaste VENDOR_HGST, 75269024Semaste VENDOR_HITACHI, 76254721Semaste VENDOR_HP, 77254721Semaste VENDOR_IBM, 78254721Semaste VENDOR_PLEXTOR, 79254721Semaste VENDOR_QUALSTAR, 80254721Semaste VENDOR_QUANTUM, 81254721Semaste VENDOR_SAMSUNG, 82254721Semaste VENDOR_SEAGATE, 83254721Semaste VENDOR_SMART, 84254721Semaste VENDOR_ATA, 85254721Semaste VENDOR_UNKNOWN 86254721Semaste} fw_vendor_t; 87254721Semaste 88254721Semaste/* 89269024Semaste * FW_TUR_READY: The drive must return good status for a test unit ready. 90263363Semaste * 91254721Semaste * FW_TUR_NOT_READY: The drive must return not ready status for a test unit 92254721Semaste * ready. You may want this in a removable media drive. 93254721Semaste * 94254721Semaste * FW_TUR_NA: It doesn't matter whether the drive is ready or not. 95254721Semaste * This may be the case for a removable media drive. 96254721Semaste */ 97254721Semastetypedef enum { 98254721Semaste FW_TUR_NONE, 99254721Semaste FW_TUR_READY, 100254721Semaste FW_TUR_NOT_READY, 101254721Semaste FW_TUR_NA 102254721Semaste} fw_tur_status; 103254721Semaste 104254721Semaste/* 105254721Semaste * FW_TIMEOUT_DEFAULT: Attempt to probe for a WRITE BUFFER timeout 106254721Semaste * value from the drive. If we get an answer, 107254721Semaste * use the Recommended timeout. Otherwise, 108254721Semaste * use the default value from the table. 109254721Semaste * 110254721Semaste * FW_TIMEOUT_DEV_REPORTED: The timeout value was probed directly from 111254721Semaste * the device. 112254721Semaste * 113254721Semaste * FW_TIMEOUT_NO_PROBE: Do not ask the device for a WRITE BUFFER 114254721Semaste * timeout value. Use the device-specific 115254721Semaste * value. 116254721Semaste * 117254721Semaste * FW_TIMEOUT_USER_SPEC: The user specified a timeout on the command 118254721Semaste * line with the -t option. This overrides any 119254721Semaste * probe or default timeout. 120254721Semaste */ 121254721Semastetypedef enum { 122254721Semaste FW_TIMEOUT_DEFAULT, 123254721Semaste FW_TIMEOUT_DEV_REPORTED, 124254721Semaste FW_TIMEOUT_NO_PROBE, 125254721Semaste FW_TIMEOUT_USER_SPEC 126254721Semaste} fw_timeout_type; 127254721Semaste 128254721Semaste/* 129254721Semaste * type: Enumeration for the particular vendor. 130254721Semaste * 131254721Semaste * pattern: Pattern to match for the Vendor ID from the SCSI 132254721Semaste * Inquiry data. 133254721Semaste * 134254721Semaste * dev_type: SCSI device type to match, or T_ANY to match any 135254721Semaste * device from the given vendor. Note that if there 136254721Semaste * is a specific device type listed for a particular 137254721Semaste * vendor, it must be listed before a T_ANY entry. 138254721Semaste * 139254721Semaste * max_pkt_size: Maximum packet size when talking to a device. Note 140254721Semaste * that although large data sizes may be supported by 141254721Semaste * the target device, they may not be supported by the 142254721Semaste * OS or the controller. 143254721Semaste * 144254721Semaste * cdb_byte2: This specifies byte 2 (byte 1 when counting from 0) 145254721Semaste * of the CDB. This is generally the WRITE BUFFER mode. 146254721Semaste * 147254721Semaste * cdb_byte2_last: This specifies byte 2 for the last chunk of the 148254721Semaste * download. 149254721Semaste * 150254721Semaste * inc_cdb_buffer_id: Increment the buffer ID by 1 for each chunk sent 151254721Semaste * down to the drive. 152254721Semaste * 153254721Semaste * inc_cdb_offset: Increment the offset field in the CDB with the byte 154254721Semaste * offset into the firmware file. 155254721Semaste * 156254721Semaste * tur_status: Pay attention to whether the device is ready before 157254721Semaste * upgrading the firmware, or not. See above for the 158254721Semaste * values. 159254721Semaste */ 160254721Semastestruct fw_vendor { 161254721Semaste fw_vendor_t type; 162254721Semaste const char *pattern; 163254721Semaste int dev_type; 164269024Semaste int max_pkt_size; 165254721Semaste u_int8_t cdb_byte2; 166254721Semaste u_int8_t cdb_byte2_last; 167254721Semaste int inc_cdb_buffer_id; 168254721Semaste int inc_cdb_offset; 169254721Semaste fw_tur_status tur_status; 170254721Semaste int timeout_ms; 171254721Semaste fw_timeout_type timeout_type; 172254721Semaste}; 173254721Semaste 174254721Semaste/* 175254721Semaste * Vendor notes: 176254721Semaste * 177254721Semaste * HGST: The packets need to be sent in multiples of 4K. 178254721Semaste * 179254721Semaste * IBM: For LTO and TS drives, the buffer ID is ignored in mode 7 (and 180254721Semaste * some other modes). It treats the request as a firmware download. 181254721Semaste * The offset (and therefore the length of each chunk sent) needs 182254721Semaste * to be a multiple of the offset boundary specified for firmware 183254721Semaste * (buffer ID 4) in the read buffer command. At least for LTO-6, 184254721Semaste * that seems to be 0, but using a 32K chunk size should satisfy 185254721Semaste * most any alignment requirement. 186254721Semaste * 187254721Semaste * SmrtStor: Mode 5 is also supported, but since the firmware is 400KB or 188254721Semaste * so, we can't fit it in a single request in most cases. 189254721Semaste */ 190254721Semastestatic struct fw_vendor vendors_list[] = { 191254721Semaste {VENDOR_HGST, "HGST", T_DIRECT, 192254721Semaste 0x1000, 0x07, 0x07, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 193254721Semaste {VENDOR_HITACHI, "HITACHI", T_ANY, 194254721Semaste 0x8000, 0x05, 0x05, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 195254721Semaste {VENDOR_HP, "HP", T_ANY, 196254721Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 197254721Semaste {VENDOR_IBM, "IBM", T_SEQUENTIAL, 198263367Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_NA, 300 * 1000, FW_TIMEOUT_DEFAULT}, 199269024Semaste {VENDOR_IBM, "IBM", T_ANY, 200254721Semaste 0x8000, 0x05, 0x05, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 201254721Semaste {VENDOR_PLEXTOR, "PLEXTOR", T_ANY, 202254721Semaste 0x2000, 0x04, 0x05, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 203254721Semaste {VENDOR_QUALSTAR, "QUALSTAR", T_ANY, 204254721Semaste 0x2030, 0x05, 0x05, 0, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 205254721Semaste {VENDOR_QUANTUM, "QUANTUM", T_ANY, 206254721Semaste 0x2000, 0x04, 0x05, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 207254721Semaste {VENDOR_SAMSUNG, "SAMSUNG", T_ANY, 208254721Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 209254721Semaste {VENDOR_SEAGATE, "SEAGATE", T_ANY, 210254721Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 211254721Semaste {VENDOR_SMART, "SmrtStor", T_DIRECT, 212254721Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 213254721Semaste 214254721Semaste /* 215254721Semaste * We match any ATA device. This is really just a placeholder, 216254721Semaste * since we won't actually send a WRITE BUFFER with any of the 217254721Semaste * listed parameters. If a SATA device is behind a SAS controller, 218254721Semaste * the SCSI to ATA translation code (at least for LSI) doesn't 219254721Semaste * generally translate a SCSI WRITE BUFFER into an ATA DOWNLOAD 220254721Semaste * MICROCODE command. So, we use the SCSI ATA PASS_THROUGH command 221254721Semaste * to send the ATA DOWNLOAD MICROCODE command instead. 222254721Semaste */ 223254721Semaste {VENDOR_ATA, "ATA", T_ANY, 224254721Semaste 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, 225254721Semaste FW_TIMEOUT_NO_PROBE}, 226254721Semaste {VENDOR_UNKNOWN, NULL, T_ANY, 227254721Semaste 0x0000, 0x00, 0x00, 0, 0, FW_TUR_NONE, WB_TIMEOUT, FW_TIMEOUT_DEFAULT} 228254721Semaste}; 229254721Semaste 230254721Semastestruct fw_timeout_desc { 231254721Semaste fw_timeout_type timeout_type; 232254721Semaste const char *timeout_desc; 233254721Semaste}; 234254721Semaste 235254721Semastestatic const struct fw_timeout_desc fw_timeout_desc_table[] = { 236254721Semaste { FW_TIMEOUT_DEFAULT, "the default" }, 237254721Semaste { FW_TIMEOUT_DEV_REPORTED, "recommended by this particular device" }, 238254721Semaste { FW_TIMEOUT_NO_PROBE, "the default" }, 239254721Semaste { FW_TIMEOUT_USER_SPEC, "what was specified on the command line" } 240254721Semaste}; 241254721Semaste 242254721Semaste#ifndef ATA_DOWNLOAD_MICROCODE 243254721Semaste#define ATA_DOWNLOAD_MICROCODE 0x92 244254721Semaste#endif 245254721Semaste 246254721Semaste#define USE_OFFSETS_FEATURE 0x3 247254721Semaste 248254721Semaste#ifndef LOW_SECTOR_SIZE 249263363Semaste#define LOW_SECTOR_SIZE 512 250263363Semaste#endif 251254721Semaste 252254721Semaste#define ATA_MAKE_LBA(o, p) \ 253254721Semaste ((((((o) / LOW_SECTOR_SIZE) >> 8) & 0xff) << 16) | \ 254269024Semaste ((((o) / LOW_SECTOR_SIZE) & 0xff) << 8) | \ 255254721Semaste ((((p) / LOW_SECTOR_SIZE) >> 8) & 0xff)) 256254721Semaste 257254721Semaste#define ATA_MAKE_SECTORS(p) (((p) / 512) & 0xff) 258254721Semaste 259254721Semaste#ifndef UNKNOWN_MAX_PKT_SIZE 260254721Semaste#define UNKNOWN_MAX_PKT_SIZE 0x8000 261254721Semaste#endif 262254721Semaste 263254721Semastestatic struct fw_vendor *fw_get_vendor(struct cam_device *cam_dev, 264263363Semaste struct ata_params *ident_buf); 265263363Semastestatic int fw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, 266254721Semaste int retry_count, int timeout); 267254721Semastestatic int fw_validate_ibm(struct cam_device *dev, int retry_count, 268254721Semaste int timeout, int fd, char *buf, 269254721Semaste const char *fw_img_path, int quiet); 270254721Semastestatic char *fw_read_img(struct cam_device *dev, int retry_count, 271254721Semaste int timeout, int quiet, const char *fw_img_path, 272254721Semaste struct fw_vendor *vp, int *num_bytes); 273254721Semastestatic int fw_check_device_ready(struct cam_device *dev, 274254721Semaste camcontrol_devtype devtype, 275254721Semaste struct fw_vendor *vp, int printerrors, 276254721Semaste int timeout); 277254721Semastestatic int fw_download_img(struct cam_device *cam_dev, 278254721Semaste struct fw_vendor *vp, char *buf, int img_size, 279254721Semaste int sim_mode, int printerrors, int quiet, 280254721Semaste int retry_count, int timeout, const char */*name*/, 281254721Semaste camcontrol_devtype devtype); 282254721Semaste 283254721Semaste/* 284254721Semaste * Find entry in vendors list that belongs to 285254721Semaste * the vendor of given cam device. 286254721Semaste */ 287254721Semastestatic struct fw_vendor * 288254721Semastefw_get_vendor(struct cam_device *cam_dev, struct ata_params *ident_buf) 289254721Semaste{ 290254721Semaste char vendor[42]; 291254721Semaste struct fw_vendor *vp; 292254721Semaste 293254721Semaste if (cam_dev == NULL) 294254721Semaste return (NULL); 295254721Semaste 296254721Semaste if (ident_buf != NULL) { 297254721Semaste cam_strvis((u_char *)vendor, ident_buf->model, 298254721Semaste sizeof(ident_buf->model), sizeof(vendor)); 299254721Semaste for (vp = vendors_list; vp->pattern != NULL; vp++) { 300254721Semaste if (vp->type == VENDOR_ATA) 301254721Semaste return (vp); 302254721Semaste } 303254721Semaste } else { 304254721Semaste cam_strvis((u_char *)vendor, (u_char *)cam_dev->inq_data.vendor, 305254721Semaste sizeof(cam_dev->inq_data.vendor), sizeof(vendor)); 306254721Semaste } 307254721Semaste for (vp = vendors_list; vp->pattern != NULL; vp++) { 308269024Semaste if (!cam_strmatch((const u_char *)vendor, 309254721Semaste (const u_char *)vp->pattern, strlen(vendor))) { 310254721Semaste if ((vp->dev_type == T_ANY) 311254721Semaste || (vp->dev_type == SID_TYPE(&cam_dev->inq_data))) 312254721Semaste break; 313263363Semaste } 314254721Semaste } 315254721Semaste return (vp); 316254721Semaste} 317254721Semaste 318254721Semastestatic int 319254721Semastefw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, 320269024Semaste int retry_count, int timeout) 321254721Semaste{ 322254721Semaste struct scsi_report_supported_opcodes_one *one; 323254721Semaste struct scsi_report_supported_opcodes_timeout *td; 324254721Semaste uint8_t *buf = NULL; 325254721Semaste uint32_t fill_len = 0, cdb_len = 0, rec_timeout = 0; 326263363Semaste int retval = 0; 327254721Semaste 328254721Semaste /* 329254721Semaste * If the user has specified a timeout on the command line, we let 330254721Semaste * him override any default or probed value. 331263363Semaste */ 332254721Semaste if (timeout != 0) { 333254721Semaste vp->timeout_type = FW_TIMEOUT_USER_SPEC; 334254721Semaste vp->timeout_ms = timeout; 335269024Semaste goto bailout; 336254721Semaste } 337254721Semaste 338254721Semaste /* 339254721Semaste * Check to see whether we should probe for a timeout for this 340254721Semaste * device. 341254721Semaste */ 342254721Semaste if (vp->timeout_type == FW_TIMEOUT_NO_PROBE) 343254721Semaste goto bailout; 344263363Semaste 345263363Semaste retval = scsigetopcodes(/*device*/ cam_dev, 346254721Semaste /*opcode_set*/ 1, 347254721Semaste /*opcode*/ WRITE_BUFFER, 348254721Semaste /*show_sa_errors*/ 1, 349254721Semaste /*sa_set*/ 0, 350254721Semaste /*service_action*/ 0, 351254721Semaste /*timeout_desc*/ 1, 352254721Semaste /*retry_count*/ retry_count, 353254721Semaste /*timeout*/ 10000, 354254721Semaste /*verbose*/ 0, 355254721Semaste /*fill_len*/ &fill_len, 356254721Semaste /*data_ptr*/ &buf); 357254721Semaste /* 358254721Semaste * It isn't an error if we can't get a timeout descriptor. We just 359254721Semaste * continue on with the default timeout. 360269024Semaste */ 361254721Semaste if (retval != 0) { 362254721Semaste retval = 0; 363254721Semaste goto bailout; 364254721Semaste } 365254721Semaste 366254721Semaste /* 367254721Semaste * Even if the drive didn't return a SCSI error, if we don't have 368254721Semaste * enough data to contain the one opcode descriptor, the CDB 369254721Semaste * structure and a timeout descriptor, we don't have the timeout 370254721Semaste * value we're looking for. So we'll just fall back to the 371263363Semaste * default value. 372263363Semaste */ 373254721Semaste if (fill_len < (sizeof(*one) + sizeof(struct scsi_write_buffer) + 374254721Semaste sizeof(*td))) 375254721Semaste goto bailout; 376254721Semaste 377254721Semaste one = (struct scsi_report_supported_opcodes_one *)buf; 378254721Semaste 379254721Semaste /* 380254721Semaste * If the drive claims to not support the WRITE BUFFER command... 381254721Semaste * fall back to the default timeout value and let things fail on 382254721Semaste * the actual firmware download. 383254721Semaste */ 384254721Semaste if ((one->support & RSO_ONE_SUP_MASK) == RSO_ONE_SUP_NOT_SUP) 385254721Semaste goto bailout; 386254721Semaste 387269024Semaste cdb_len = scsi_2btoul(one->cdb_length); 388254721Semaste td = (struct scsi_report_supported_opcodes_timeout *) 389254721Semaste &buf[sizeof(*one) + cdb_len]; 390254721Semaste 391254721Semaste rec_timeout = scsi_4btoul(td->recommended_time); 392254721Semaste /* 393254721Semaste * If the recommended timeout is 0, then the device has probably 394254721Semaste * returned a bogus value. 395254721Semaste */ 396254721Semaste if (rec_timeout == 0) 397254721Semaste goto bailout; 398254721Semaste 399263363Semaste /* CAM timeouts are in ms */ 400263363Semaste rec_timeout *= 1000; 401254721Semaste 402254721Semaste vp->timeout_ms = rec_timeout; 403254721Semaste vp->timeout_type = FW_TIMEOUT_DEV_REPORTED; 404254721Semaste 405254721Semastebailout: 406254721Semaste return (retval); 407254721Semaste} 408254721Semaste 409254721Semaste#define SVPD_IBM_FW_DESIGNATION 0x03 410254721Semaste 411254721Semaste/* 412254721Semaste * IBM LTO and TS tape drives have an INQUIRY VPD page 0x3 with the following 413254721Semaste * format: 414254721Semaste */ 415269024Semastestruct fw_ibm_tape_fw_designation { 416254721Semaste uint8_t device; 417254721Semaste uint8_t page_code; 418254721Semaste uint8_t reserved; 419254721Semaste uint8_t length; 420254721Semaste uint8_t ascii_length; 421254721Semaste uint8_t reserved2[3]; 422254721Semaste uint8_t load_id[4]; 423254721Semaste uint8_t fw_rev[4]; 424254721Semaste uint8_t ptf_number[4]; 425254721Semaste uint8_t patch_number[4]; 426254721Semaste uint8_t ru_name[8]; 427254721Semaste uint8_t lib_seq_num[5]; 428254721Semaste}; 429254721Semaste 430254721Semaste/* 431254721Semaste * The firmware for IBM tape drives has the following header format. The 432254721Semaste * load_id and ru_name in the header file should match what is returned in 433254721Semaste * VPD page 0x3. 434254721Semaste */ 435254721Semastestruct fw_ibm_tape_fw_header { 436254721Semaste uint8_t unspec[4]; 437254721Semaste uint8_t length[4]; /* Firmware and header! */ 438254721Semaste uint8_t load_id[4]; 439254721Semaste uint8_t fw_rev[4]; 440254721Semaste uint8_t reserved[8]; 441254721Semaste uint8_t ru_name[8]; 442254721Semaste}; 443254721Semaste 444254721Semastestatic int 445254721Semastefw_validate_ibm(struct cam_device *dev, int retry_count, int timeout, int fd, 446254721Semaste char *buf, const char *fw_img_path, int quiet) 447254721Semaste{ 448254721Semaste union ccb *ccb; 449254721Semaste struct fw_ibm_tape_fw_designation vpd_page; 450254721Semaste struct fw_ibm_tape_fw_header *header; 451254721Semaste char drive_rev[sizeof(vpd_page.fw_rev) + 1]; 452254721Semaste char file_rev[sizeof(vpd_page.fw_rev) + 1]; 453254721Semaste int retval = 1; 454254721Semaste 455254721Semaste ccb = cam_getccb(dev); 456254721Semaste if (ccb == NULL) { 457254721Semaste warnx("couldn't allocate CCB"); 458254721Semaste goto bailout; 459254721Semaste } 460254721Semaste 461254721Semaste /* cam_getccb cleans up the header, caller has to zero the payload */ 462254721Semaste bzero(&(&ccb->ccb_h)[1], 463254721Semaste sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 464254721Semaste 465254721Semaste bzero(&vpd_page, sizeof(vpd_page)); 466254721Semaste 467254721Semaste scsi_inquiry(&ccb->csio, 468254721Semaste /*retries*/ retry_count, 469254721Semaste /*cbfcnp*/ NULL, 470254721Semaste /* tag_action */ MSG_SIMPLE_Q_TAG, 471254721Semaste /* inq_buf */ (u_int8_t *)&vpd_page, 472254721Semaste /* inq_len */ sizeof(vpd_page), 473254721Semaste /* evpd */ 1, 474254721Semaste /* page_code */ SVPD_IBM_FW_DESIGNATION, 475254721Semaste /* sense_len */ SSD_FULL_SIZE, 476254721Semaste /* timeout */ timeout ? timeout : 5000); 477254721Semaste 478254721Semaste /* Disable freezing the device queue */ 479254721Semaste ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 480254721Semaste 481254721Semaste if (retry_count != 0) 482254721Semaste ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 483254721Semaste 484254721Semaste if (cam_send_ccb(dev, ccb) < 0) { 485263363Semaste warn("error getting firmware designation page"); 486263363Semaste 487254721Semaste cam_error_print(dev, ccb, CAM_ESF_ALL, 488254721Semaste CAM_EPF_ALL, stderr); 489254721Semaste 490254721Semaste cam_freeccb(ccb); 491254721Semaste goto bailout; 492254721Semaste } 493269024Semaste 494254721Semaste if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 495254721Semaste cam_error_print(dev, ccb, CAM_ESF_ALL, 496254721Semaste CAM_EPF_ALL, stderr); 497254721Semaste goto bailout; 498254721Semaste } 499254721Semaste 500254721Semaste /* 501254721Semaste * Read the firmware header only. 502254721Semaste */ 503269024Semaste if (read(fd, buf, sizeof(*header)) != sizeof(*header)) { 504254721Semaste warn("unable to read %zu bytes from %s", sizeof(*header), 505254721Semaste fw_img_path); 506254721Semaste goto bailout; 507254721Semaste } 508269024Semaste 509254721Semaste /* Rewind the file back to 0 for the full file read. */ 510254721Semaste if (lseek(fd, 0, SEEK_SET) == -1) { 511254721Semaste warn("Unable to lseek"); 512254721Semaste goto bailout; 513254721Semaste } 514254721Semaste 515254721Semaste header = (struct fw_ibm_tape_fw_header *)buf; 516254721Semaste 517254721Semaste bzero(drive_rev, sizeof(drive_rev)); 518254721Semaste bcopy(vpd_page.fw_rev, drive_rev, sizeof(vpd_page.fw_rev)); 519254721Semaste bzero(file_rev, sizeof(file_rev)); 520254721Semaste bcopy(header->fw_rev, file_rev, sizeof(header->fw_rev)); 521254721Semaste 522254721Semaste if (quiet == 0) { 523254721Semaste fprintf(stdout, "Current Drive Firmware version: %s\n", 524254721Semaste drive_rev); 525254721Semaste fprintf(stdout, "Firmware File version: %s\n", file_rev); 526254721Semaste } 527254721Semaste 528254721Semaste /* 529254721Semaste * For IBM tape drives the load ID and RU name reported by the 530254721Semaste * drive should match what is in the firmware file. 531254721Semaste */ 532254721Semaste if (bcmp(vpd_page.load_id, header->load_id, 533254721Semaste MIN(sizeof(vpd_page.load_id), sizeof(header->load_id))) != 0) { 534254721Semaste warnx("Drive Firmware load ID 0x%x does not match firmware " 535254721Semaste "file load ID 0x%x", scsi_4btoul(vpd_page.load_id), 536254721Semaste scsi_4btoul(header->load_id)); 537254721Semaste goto bailout; 538254721Semaste } 539254721Semaste 540254721Semaste if (bcmp(vpd_page.ru_name, header->ru_name, 541254721Semaste MIN(sizeof(vpd_page.ru_name), sizeof(header->ru_name))) != 0) { 542254721Semaste warnx("Drive Firmware RU name 0x%jx does not match firmware " 543254721Semaste "file RU name 0x%jx", 544254721Semaste (uintmax_t)scsi_8btou64(vpd_page.ru_name), 545254721Semaste (uintmax_t)scsi_8btou64(header->ru_name)); 546254721Semaste goto bailout; 547254721Semaste } 548254721Semaste if (quiet == 0) 549254721Semaste fprintf(stdout, "Firmware file is valid for this drive.\n"); 550254721Semaste retval = 0; 551254721Semastebailout: 552254721Semaste cam_freeccb(ccb); 553254721Semaste 554254721Semaste return (retval); 555254721Semaste} 556254721Semaste 557254721Semaste/* 558254721Semaste * Allocate a buffer and read fw image file into it 559254721Semaste * from given path. Number of bytes read is stored 560254721Semaste * in num_bytes. 561254721Semaste */ 562254721Semastestatic char * 563254721Semastefw_read_img(struct cam_device *dev, int retry_count, int timeout, int quiet, 564254721Semaste const char *fw_img_path, struct fw_vendor *vp, int *num_bytes) 565254721Semaste{ 566254721Semaste int fd; 567254721Semaste struct stat stbuf; 568254721Semaste char *buf; 569254721Semaste off_t img_size; 570254721Semaste int skip_bytes = 0; 571254721Semaste 572254721Semaste if ((fd = open(fw_img_path, O_RDONLY)) < 0) { 573254721Semaste warn("Could not open image file %s", fw_img_path); 574254721Semaste return (NULL); 575254721Semaste } 576254721Semaste if (fstat(fd, &stbuf) < 0) { 577254721Semaste warn("Could not stat image file %s", fw_img_path); 578254721Semaste goto bailout1; 579254721Semaste } 580254721Semaste if ((img_size = stbuf.st_size) == 0) { 581254721Semaste warnx("Zero length image file %s", fw_img_path); 582254721Semaste goto bailout1; 583254721Semaste } 584254721Semaste if ((buf = malloc(img_size)) == NULL) { 585254721Semaste warnx("Could not allocate buffer to read image file %s", 586254721Semaste fw_img_path); 587254721Semaste goto bailout1; 588254721Semaste } 589254721Semaste /* Skip headers if applicable. */ 590254721Semaste switch (vp->type) { 591254721Semaste case VENDOR_SEAGATE: 592254721Semaste if (read(fd, buf, 16) != 16) { 593254721Semaste warn("Could not read image file %s", fw_img_path); 594254721Semaste goto bailout; 595254721Semaste } 596254721Semaste if (lseek(fd, 0, SEEK_SET) == -1) { 597254721Semaste warn("Unable to lseek"); 598254721Semaste goto bailout; 599254721Semaste } 600254721Semaste if ((strncmp(buf, "SEAGATE,SEAGATE ", 16) == 0) || 601254721Semaste (img_size % 512 == 80)) 602254721Semaste skip_bytes = 80; 603254721Semaste break; 604254721Semaste case VENDOR_QUALSTAR: 605254721Semaste skip_bytes = img_size % 1030; 606254721Semaste break; 607254721Semaste case VENDOR_IBM: { 608254721Semaste if (vp->dev_type != T_SEQUENTIAL) 609254721Semaste break; 610254721Semaste if (fw_validate_ibm(dev, retry_count, timeout, fd, buf, 611254721Semaste fw_img_path, quiet) != 0) 612254721Semaste goto bailout; 613254721Semaste break; 614254721Semaste } 615254721Semaste default: 616254721Semaste break; 617254721Semaste } 618254721Semaste if (skip_bytes != 0) { 619254721Semaste fprintf(stdout, "Skipping %d byte header.\n", skip_bytes); 620254721Semaste if (lseek(fd, skip_bytes, SEEK_SET) == -1) { 621254721Semaste warn("Could not lseek"); 622254721Semaste goto bailout; 623254721Semaste } 624254721Semaste img_size -= skip_bytes; 625254721Semaste } 626254721Semaste /* Read image into a buffer. */ 627254721Semaste if (read(fd, buf, img_size) != img_size) { 628254721Semaste warn("Could not read image file %s", fw_img_path); 629254721Semaste goto bailout; 630254721Semaste } 631254721Semaste *num_bytes = img_size; 632254721Semaste close(fd); 633254721Semaste return (buf); 634254721Semastebailout: 635254721Semaste free(buf); 636254721Semastebailout1: 637254721Semaste close(fd); 638263363Semaste *num_bytes = 0; 639254721Semaste return (NULL); 640254721Semaste} 641254721Semaste 642254721Semaste/* 643254721Semaste * Returns 0 for "success", where success means that the device has met the 644254721Semaste * requirement in the vendor structure for being ready or not ready when 645254721Semaste * firmware is downloaded. 646254721Semaste * 647254721Semaste * Returns 1 for a failure to be ready to accept a firmware download. 648254721Semaste * (e.g., a drive needs to be ready, but returns not ready) 649254721Semaste * 650254721Semaste * Returns -1 for any other failure. 651254721Semaste */ 652254721Semastestatic int 653254721Semastefw_check_device_ready(struct cam_device *dev, camcontrol_devtype devtype, 654254721Semaste struct fw_vendor *vp, int printerrors, int timeout) 655254721Semaste{ 656254721Semaste union ccb *ccb; 657254721Semaste int retval = 0; 658254721Semaste int16_t *ptr = NULL; 659254721Semaste size_t dxfer_len = 0; 660254721Semaste 661254721Semaste if ((ccb = cam_getccb(dev)) == NULL) { 662254721Semaste warnx("Could not allocate CCB"); 663254721Semaste retval = -1; 664254721Semaste goto bailout; 665254721Semaste } 666254721Semaste 667254721Semaste bzero(&(&ccb->ccb_h)[1], 668254721Semaste sizeof(union ccb) - sizeof(struct ccb_hdr)); 669254721Semaste 670254721Semaste if (devtype != CC_DT_SCSI) { 671254721Semaste dxfer_len = sizeof(struct ata_params); 672254721Semaste 673254721Semaste ptr = (uint16_t *)malloc(dxfer_len); 674254721Semaste if (ptr == NULL) { 675254721Semaste warnx("can't malloc memory for identify"); 676254721Semaste retval = -1; 677254721Semaste goto bailout; 678254721Semaste } 679254721Semaste bzero(ptr, dxfer_len); 680254721Semaste } 681254721Semaste 682254721Semaste switch (devtype) { 683254721Semaste case CC_DT_SCSI: 684254721Semaste scsi_test_unit_ready(&ccb->csio, 685254721Semaste /*retries*/ 0, 686254721Semaste /*cbfcnp*/ NULL, 687254721Semaste /*tag_action*/ MSG_SIMPLE_Q_TAG, 688254721Semaste /*sense_len*/ SSD_FULL_SIZE, 689254721Semaste /*timeout*/ 5000); 690254721Semaste break; 691254721Semaste case CC_DT_ATA_BEHIND_SCSI: 692254721Semaste case CC_DT_ATA: { 693254721Semaste build_ata_cmd(ccb, 694254721Semaste /*retries*/ 1, 695254721Semaste /*flags*/ CAM_DIR_IN, 696254721Semaste /*tag_action*/ MSG_SIMPLE_Q_TAG, 697254721Semaste /*protocol*/ AP_PROTO_PIO_IN, 698254721Semaste /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES | 699254721Semaste AP_FLAG_TLEN_SECT_CNT | 700254721Semaste AP_FLAG_TDIR_FROM_DEV, 701254721Semaste /*features*/ 0, 702254721Semaste /*sector_count*/ (uint8_t) dxfer_len, 703254721Semaste /*lba*/ 0, 704254721Semaste /*command*/ ATA_ATA_IDENTIFY, 705254721Semaste /*data_ptr*/ (uint8_t *)ptr, 706254721Semaste /*dxfer_len*/ dxfer_len, 707254721Semaste /*sense_len*/ SSD_FULL_SIZE, 708254721Semaste /*timeout*/ timeout ? timeout : 30 * 1000, 709254721Semaste /*is48bit*/ 0, 710254721Semaste /*devtype*/ devtype); 711254721Semaste break; 712254721Semaste } 713254721Semaste default: 714254721Semaste warnx("Unknown disk type %d", devtype); 715254721Semaste retval = -1; 716254721Semaste goto bailout; 717254721Semaste break; /*NOTREACHED*/ 718254721Semaste } 719254721Semaste 720254721Semaste ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 721254721Semaste 722254721Semaste retval = cam_send_ccb(dev, ccb); 723254721Semaste if (retval != 0) { 724254721Semaste warn("error sending %s CCB", (devtype == CC_DT_SCSI) ? 725254721Semaste "Test Unit Ready" : "Identify"); 726254721Semaste retval = -1; 727254721Semaste goto bailout; 728254721Semaste } 729254721Semaste 730254721Semaste if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 731254721Semaste && (vp->tur_status == FW_TUR_READY)) { 732254721Semaste warnx("Device is not ready"); 733254721Semaste if (printerrors) 734254721Semaste cam_error_print(dev, ccb, CAM_ESF_ALL, 735254721Semaste CAM_EPF_ALL, stderr); 736254721Semaste retval = 1; 737254721Semaste goto bailout; 738254721Semaste } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 739254721Semaste && (vp->tur_status == FW_TUR_NOT_READY)) { 740254721Semaste warnx("Device cannot have media loaded when firmware is " 741254721Semaste "downloaded"); 742254721Semaste retval = 1; 743254721Semaste goto bailout; 744254721Semaste } 745254721Semastebailout: 746254721Semaste if (ccb != NULL) 747254721Semaste cam_freeccb(ccb); 748254721Semaste 749254721Semaste return (retval); 750254721Semaste} 751254721Semaste 752254721Semaste/* 753254721Semaste * Download firmware stored in buf to cam_dev. If simulation mode 754254721Semaste * is enabled, only show what packet sizes would be sent to the 755254721Semaste * device but do not sent any actual packets 756254721Semaste */ 757254721Semastestatic int 758254721Semastefw_download_img(struct cam_device *cam_dev, struct fw_vendor *vp, 759254721Semaste char *buf, int img_size, int sim_mode, int printerrors, int quiet, 760254721Semaste int retry_count, int timeout, const char *imgname, 761254721Semaste camcontrol_devtype devtype) 762254721Semaste{ 763254721Semaste struct scsi_write_buffer cdb; 764254721Semaste progress_t progress; 765254721Semaste int size = 0; 766254721Semaste union ccb *ccb = NULL; 767254721Semaste int pkt_count = 0; 768254721Semaste int max_pkt_size; 769254721Semaste u_int32_t pkt_size = 0; 770254721Semaste char *pkt_ptr = buf; 771254721Semaste u_int32_t offset; 772254721Semaste int last_pkt = 0; 773254721Semaste int retval = 0; 774254721Semaste 775254721Semaste /* 776254721Semaste * Check to see whether the device is ready to accept a firmware 777254721Semaste * download. 778254721Semaste */ 779254721Semaste retval = fw_check_device_ready(cam_dev, devtype, vp, printerrors, 780254721Semaste timeout); 781254721Semaste if (retval != 0) 782254721Semaste goto bailout; 783254721Semaste 784254721Semaste if ((ccb = cam_getccb(cam_dev)) == NULL) { 785254721Semaste warnx("Could not allocate CCB"); 786254721Semaste retval = 1; 787254721Semaste goto bailout; 788254721Semaste } 789254721Semaste 790254721Semaste bzero(&(&ccb->ccb_h)[1], 791254721Semaste sizeof(union ccb) - sizeof(struct ccb_hdr)); 792254721Semaste 793254721Semaste max_pkt_size = vp->max_pkt_size; 794254721Semaste if (max_pkt_size == 0) 795254721Semaste max_pkt_size = UNKNOWN_MAX_PKT_SIZE; 796254721Semaste 797254721Semaste pkt_size = max_pkt_size; 798254721Semaste progress_init(&progress, imgname, size = img_size); 799254721Semaste /* Download single fw packets. */ 800254721Semaste do { 801254721Semaste if (img_size <= max_pkt_size) { 802254721Semaste last_pkt = 1; 803254721Semaste pkt_size = img_size; 804254721Semaste } 805254721Semaste progress_update(&progress, size - img_size); 806254721Semaste if (((sim_mode == 0) && (quiet == 0)) 807254721Semaste || ((sim_mode != 0) && (printerrors == 0))) 808254721Semaste progress_draw(&progress); 809254721Semaste bzero(&cdb, sizeof(cdb)); 810254721Semaste switch (devtype) { 811254721Semaste case CC_DT_SCSI: 812254721Semaste cdb.opcode = WRITE_BUFFER; 813254721Semaste cdb.control = 0; 814254721Semaste /* Parameter list length. */ 815254721Semaste scsi_ulto3b(pkt_size, &cdb.length[0]); 816254721Semaste offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0; 817254721Semaste scsi_ulto3b(offset, &cdb.offset[0]); 818254721Semaste cdb.byte2 = last_pkt ? vp->cdb_byte2_last : 819254721Semaste vp->cdb_byte2; 820254721Semaste cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0; 821254721Semaste /* Zero out payload of ccb union after ccb header. */ 822254721Semaste bzero(&(&ccb->ccb_h)[1], 823254721Semaste sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr)); 824254721Semaste /* 825254721Semaste * Copy previously constructed cdb into ccb_scsiio 826254721Semaste * struct. 827254721Semaste */ 828254721Semaste bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0], 829254721Semaste sizeof(struct scsi_write_buffer)); 830254721Semaste /* Fill rest of ccb_scsiio struct. */ 831254721Semaste cam_fill_csio(&ccb->csio, /* ccb_scsiio*/ 832254721Semaste retry_count, /* retries*/ 833254721Semaste NULL, /* cbfcnp*/ 834254721Semaste CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags*/ 835254721Semaste CAM_TAG_ACTION_NONE, /* tag_action*/ 836254721Semaste (u_char *)pkt_ptr, /* data_ptr*/ 837254721Semaste pkt_size, /* dxfer_len*/ 838254721Semaste SSD_FULL_SIZE, /* sense_len*/ 839254721Semaste sizeof(struct scsi_write_buffer), /* cdb_len*/ 840254721Semaste timeout ? timeout : WB_TIMEOUT); /* timeout*/ 841254721Semaste break; 842254721Semaste case CC_DT_ATA: 843254721Semaste case CC_DT_ATA_BEHIND_SCSI: { 844254721Semaste uint32_t off; 845254721Semaste 846254721Semaste off = (uint32_t)(pkt_ptr - buf); 847254721Semaste 848254721Semaste build_ata_cmd(ccb, 849254721Semaste /*retry_count*/ retry_count, 850254721Semaste /*flags*/ CAM_DIR_OUT | CAM_DEV_QFRZDIS, 851254721Semaste /*tag_action*/ CAM_TAG_ACTION_NONE, 852254721Semaste /*protocol*/ AP_PROTO_PIO_OUT, 853254721Semaste /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES | 854254721Semaste AP_FLAG_TLEN_SECT_CNT | 855254721Semaste AP_FLAG_TDIR_TO_DEV, 856254721Semaste /*features*/ USE_OFFSETS_FEATURE, 857254721Semaste /*sector_count*/ ATA_MAKE_SECTORS(pkt_size), 858254721Semaste /*lba*/ ATA_MAKE_LBA(off, pkt_size), 859254721Semaste /*command*/ ATA_DOWNLOAD_MICROCODE, 860254721Semaste /*data_ptr*/ (uint8_t *)pkt_ptr, 861254721Semaste /*dxfer_len*/ pkt_size, 862254721Semaste /*sense_len*/ SSD_FULL_SIZE, 863254721Semaste /*timeout*/ timeout ? timeout : WB_TIMEOUT, 864254721Semaste /*is48bit*/ 0, 865254721Semaste /*devtype*/ devtype); 866254721Semaste break; 867254721Semaste } 868254721Semaste default: 869254721Semaste warnx("Unknown device type %d", devtype); 870254721Semaste retval = 1; 871254721Semaste goto bailout; 872254721Semaste break; /*NOTREACHED*/ 873254721Semaste } 874254721Semaste if (!sim_mode) { 875254721Semaste /* Execute the command. */ 876254721Semaste if (cam_send_ccb(cam_dev, ccb) < 0 || 877254721Semaste (ccb->ccb_h.status & CAM_STATUS_MASK) != 878254721Semaste CAM_REQ_CMP) { 879254721Semaste warnx("Error writing image to device"); 880254721Semaste if (printerrors) 881254721Semaste cam_error_print(cam_dev, ccb, 882254721Semaste CAM_ESF_ALL, CAM_EPF_ALL, stderr); 883254721Semaste retval = 1; 884254721Semaste goto bailout; 885254721Semaste } 886254721Semaste } else if (printerrors) { 887254721Semaste cam_error_print(cam_dev, ccb, CAM_ESF_COMMAND, 0, 888254721Semaste stdout); 889254721Semaste } 890254721Semaste 891254721Semaste /* Prepare next round. */ 892254721Semaste pkt_count++; 893254721Semaste pkt_ptr += pkt_size; 894254721Semaste img_size -= pkt_size; 895254721Semaste } while(!last_pkt); 896254721Semastebailout: 897254721Semaste if (quiet == 0) 898254721Semaste progress_complete(&progress, size - img_size); 899254721Semaste if (ccb != NULL) 900254721Semaste cam_freeccb(ccb); 901254721Semaste return (retval); 902254721Semaste} 903254721Semaste 904254721Semasteint 905254721Semastefwdownload(struct cam_device *device, int argc, char **argv, 906254721Semaste char *combinedopt, int printerrors, int retry_count, int timeout) 907254721Semaste{ 908254721Semaste struct fw_vendor *vp; 909254721Semaste char *fw_img_path = NULL; 910254721Semaste struct ata_params *ident_buf = NULL; 911254721Semaste camcontrol_devtype devtype; 912254721Semaste char *buf = NULL; 913254721Semaste int img_size; 914254721Semaste int c; 915254721Semaste int sim_mode = 0; 916254721Semaste int confirmed = 0; 917254721Semaste int quiet = 0; 918254721Semaste int retval = 0; 919254721Semaste 920254721Semaste while ((c = getopt(argc, argv, combinedopt)) != -1) { 921254721Semaste switch (c) { 922254721Semaste case 'f': 923254721Semaste fw_img_path = optarg; 924254721Semaste break; 925254721Semaste case 'q': 926254721Semaste quiet = 1; 927254721Semaste break; 928254721Semaste case 's': 929254721Semaste sim_mode = 1; 930254721Semaste break; 931254721Semaste case 'y': 932254721Semaste confirmed = 1; 933254721Semaste break; 934254721Semaste default: 935254721Semaste break; 936254721Semaste } 937254721Semaste } 938254721Semaste 939254721Semaste if (fw_img_path == NULL) 940254721Semaste errx(1, "you must specify a firmware image file using -f " 941254721Semaste "option"); 942254721Semaste 943254721Semaste retval = get_device_type(device, retry_count, timeout, printerrors, 944254721Semaste &devtype); 945254721Semaste if (retval != 0) 946254721Semaste errx(1, "Unable to determine device type"); 947254721Semaste 948254721Semaste if ((devtype == CC_DT_ATA) 949254721Semaste || (devtype == CC_DT_ATA_BEHIND_SCSI)) { 950254721Semaste union ccb *ccb; 951254721Semaste 952254721Semaste ccb = cam_getccb(device); 953254721Semaste if (ccb == NULL) { 954254721Semaste warnx("couldn't allocate CCB"); 955254721Semaste retval = 1; 956254721Semaste goto bailout; 957254721Semaste } 958254721Semaste 959254721Semaste if (ata_do_identify(device, retry_count, timeout, ccb, 960254721Semaste &ident_buf) != 0) { 961254721Semaste cam_freeccb(ccb); 962254721Semaste retval = 1; 963254721Semaste goto bailout; 964254721Semaste } 965254721Semaste } else if (devtype != CC_DT_SCSI) 966254721Semaste errx(1, "Unsupported device type %d", devtype); 967254721Semaste 968254721Semaste vp = fw_get_vendor(device, ident_buf); 969254721Semaste /* 970254721Semaste * Bail out if we have an unknown vendor and this isn't an ATA 971254721Semaste * disk. For a SCSI disk, we have no chance of working properly 972254721Semaste * with the default values in the VENDOR_UNKNOWN case. For an ATA 973254721Semaste * disk connected via an ATA transport, we may work for drives that 974254721Semaste * support the ATA_DOWNLOAD_MICROCODE command. 975254721Semaste */ 976254721Semaste if (((vp == NULL) 977254721Semaste || (vp->type == VENDOR_UNKNOWN)) 978254721Semaste && (devtype == CC_DT_SCSI)) 979254721Semaste errx(1, "Unsupported device"); 980254721Semaste 981254721Semaste retval = fw_get_timeout(device, vp, retry_count, timeout); 982254721Semaste if (retval != 0) { 983254721Semaste warnx("Unable to get a firmware download timeout value"); 984254721Semaste goto bailout; 985254721Semaste } 986254721Semaste 987254721Semaste buf = fw_read_img(device, retry_count, timeout, quiet, fw_img_path, 988254721Semaste vp, &img_size); 989254721Semaste if (buf == NULL) { 990254721Semaste retval = 1; 991254721Semaste goto bailout; 992254721Semaste } 993254721Semaste 994254721Semaste if (!confirmed) { 995254721Semaste fprintf(stdout, "You are about to download firmware image (%s)" 996254721Semaste " into the following device:\n", 997254721Semaste fw_img_path); 998254721Semaste if (devtype == CC_DT_SCSI) { 999254721Semaste if (scsidoinquiry(device, argc, argv, combinedopt, 0, 1000254721Semaste 5000) != 0) { 1001254721Semaste warnx("Error sending inquiry"); 1002254721Semaste retval = 1; 1003254721Semaste goto bailout; 1004254721Semaste } 1005254721Semaste } else { 1006254721Semaste printf("%s%d: ", device->device_name, 1007254721Semaste device->dev_unit_num); 1008254721Semaste ata_print_ident(ident_buf); 1009254721Semaste camxferrate(device); 1010269024Semaste free(ident_buf); 1011254721Semaste } 1012254721Semaste fprintf(stdout, "Using a timeout of %u ms, which is %s.\n", 1013254721Semaste vp->timeout_ms, 1014269024Semaste fw_timeout_desc_table[vp->timeout_type].timeout_desc); 1015254721Semaste fprintf(stdout, "\nIt may damage your drive. "); 1016254721Semaste if (!get_confirmation()) { 1017254721Semaste retval = 1; 1018254721Semaste goto bailout; 1019254721Semaste } 1020263367Semaste } 1021254721Semaste if ((sim_mode != 0) && (quiet == 0)) 1022263367Semaste fprintf(stdout, "Running in simulation mode\n"); 1023269024Semaste 1024254721Semaste if (fw_download_img(device, vp, buf, img_size, sim_mode, printerrors, 1025254721Semaste quiet, retry_count, vp->timeout_ms, fw_img_path, devtype) != 0) { 1026254721Semaste fprintf(stderr, "Firmware download failed\n"); 1027254721Semaste retval = 1; 1028263363Semaste goto bailout; 1029263363Semaste } else if (quiet == 0) 1030263363Semaste fprintf(stdout, "Firmware download successful\n"); 1031263367Semaste 1032263367Semastebailout: 1033263367Semaste free(buf); 1034263367Semaste return (retval); 1035263367Semaste} 1036263367Semaste 1037263367Semaste