1227961Semaste/*- 2227961Semaste * Copyright (c) 2011 Sandvine Incorporated. All rights reserved. 3227961Semaste * Copyright (c) 2002-2011 Andre Albsmeier <andre@albsmeier.net> 4227961Semaste * All rights reserved. 5227961Semaste * 6227961Semaste * Redistribution and use in source and binary forms, with or without 7227961Semaste * modification, are permitted provided that the following conditions 8227961Semaste * are met: 9227961Semaste * 1. Redistributions of source code must retain the above copyright 10227961Semaste * notice, this list of conditions and the following disclaimer, 11227961Semaste * without modification, immediately at the beginning of the file. 12227961Semaste * 2. Redistributions in binary form must reproduce the above copyright 13227961Semaste * notice, this list of conditions and the following disclaimer in the 14227961Semaste * documentation and/or other materials provided with the distribution. 15227961Semaste * 16227961Semaste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17227961Semaste * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18227961Semaste * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19227961Semaste * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20227961Semaste * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21227961Semaste * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22227961Semaste * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23227961Semaste * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24227961Semaste * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25227961Semaste * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26227961Semaste */ 27227961Semaste 28227961Semaste/* 29228203Semaste * This software is derived from Andre Albsmeier's fwprog.c which contained 30228203Semaste * the following note: 31228203Semaste * 32228203Semaste * Many thanks goes to Marc Frajola <marc@terasolutions.com> from 33228203Semaste * TeraSolutions for the initial idea and his programme for upgrading 34228203Semaste * the firmware of I*M DDYS drives. 35228203Semaste */ 36228203Semaste 37228203Semaste/* 38227961Semaste * BEWARE: 39227961Semaste * 40227961Semaste * The fact that you see your favorite vendor listed below does not 41227961Semaste * imply that your equipment won't break when you use this software 42227961Semaste * with it. It only means that the firmware of at least one device type 43227961Semaste * of each vendor listed has been programmed successfully using this code. 44227961Semaste * 45227961Semaste * The -s option simulates a download but does nothing apart from that. 46227961Semaste * It can be used to check what chunk sizes would have been used with the 47227961Semaste * specified device. 48227961Semaste */ 49227961Semaste 50227961Semaste#include <sys/cdefs.h> 51227961Semaste__FBSDID("$FreeBSD: stable/10/sbin/camcontrol/fwdownload.c 319266 2017-05-30 22:46:00Z asomers $"); 52227961Semaste 53227961Semaste#include <sys/types.h> 54227961Semaste#include <sys/stat.h> 55227961Semaste 56227961Semaste#include <err.h> 57227961Semaste#include <fcntl.h> 58227961Semaste#include <stdio.h> 59227961Semaste#include <stdlib.h> 60227961Semaste#include <string.h> 61227961Semaste#include <unistd.h> 62227961Semaste 63227961Semaste#include <cam/scsi/scsi_all.h> 64227961Semaste#include <cam/scsi/scsi_message.h> 65227961Semaste#include <camlib.h> 66227961Semaste 67237281Sscottl#include "progress.h" 68237281Sscottl 69227961Semaste#include "camcontrol.h" 70227961Semaste 71287203Sken#define WB_TIMEOUT 50000 /* 50 seconds */ 72227961Semaste 73227961Semastetypedef enum { 74287203Sken VENDOR_HGST, 75227961Semaste VENDOR_HITACHI, 76227961Semaste VENDOR_HP, 77227961Semaste VENDOR_IBM, 78227961Semaste VENDOR_PLEXTOR, 79237281Sscottl VENDOR_QUALSTAR, 80227961Semaste VENDOR_QUANTUM, 81255310Sbryanv VENDOR_SAMSUNG, 82227961Semaste VENDOR_SEAGATE, 83287203Sken VENDOR_SMART, 84287203Sken VENDOR_ATA, 85227961Semaste VENDOR_UNKNOWN 86227961Semaste} fw_vendor_t; 87227961Semaste 88287203Sken/* 89287203Sken * FW_TUR_READY: The drive must return good status for a test unit ready. 90287203Sken * 91287203Sken * FW_TUR_NOT_READY: The drive must return not ready status for a test unit 92287203Sken * ready. You may want this in a removable media drive. 93287203Sken * 94287203Sken * FW_TUR_NA: It doesn't matter whether the drive is ready or not. 95287203Sken * This may be the case for a removable media drive. 96287203Sken */ 97287203Skentypedef enum { 98287203Sken FW_TUR_NONE, 99287203Sken FW_TUR_READY, 100287203Sken FW_TUR_NOT_READY, 101287203Sken FW_TUR_NA 102287203Sken} fw_tur_status; 103287203Sken 104287203Sken/* 105287203Sken * FW_TIMEOUT_DEFAULT: Attempt to probe for a WRITE BUFFER timeout 106287203Sken * value from the drive. If we get an answer, 107287203Sken * use the Recommended timeout. Otherwise, 108287203Sken * use the default value from the table. 109287203Sken * 110287203Sken * FW_TIMEOUT_DEV_REPORTED: The timeout value was probed directly from 111287203Sken * the device. 112287203Sken * 113287203Sken * FW_TIMEOUT_NO_PROBE: Do not ask the device for a WRITE BUFFER 114287203Sken * timeout value. Use the device-specific 115287203Sken * value. 116287203Sken * 117287203Sken * FW_TIMEOUT_USER_SPEC: The user specified a timeout on the command 118287203Sken * line with the -t option. This overrides any 119287203Sken * probe or default timeout. 120287203Sken */ 121287203Skentypedef enum { 122287203Sken FW_TIMEOUT_DEFAULT, 123287203Sken FW_TIMEOUT_DEV_REPORTED, 124287203Sken FW_TIMEOUT_NO_PROBE, 125287203Sken FW_TIMEOUT_USER_SPEC 126287203Sken} fw_timeout_type; 127287203Sken 128287203Sken/* 129287203Sken * type: Enumeration for the particular vendor. 130287203Sken * 131287203Sken * pattern: Pattern to match for the Vendor ID from the SCSI 132287203Sken * Inquiry data. 133287203Sken * 134287203Sken * dev_type: SCSI device type to match, or T_ANY to match any 135287203Sken * device from the given vendor. Note that if there 136287203Sken * is a specific device type listed for a particular 137287203Sken * vendor, it must be listed before a T_ANY entry. 138287203Sken * 139287203Sken * max_pkt_size: Maximum packet size when talking to a device. Note 140287203Sken * that although large data sizes may be supported by 141287203Sken * the target device, they may not be supported by the 142287203Sken * OS or the controller. 143287203Sken * 144287203Sken * cdb_byte2: This specifies byte 2 (byte 1 when counting from 0) 145287203Sken * of the CDB. This is generally the WRITE BUFFER mode. 146287203Sken * 147287203Sken * cdb_byte2_last: This specifies byte 2 for the last chunk of the 148287203Sken * download. 149287203Sken * 150287203Sken * inc_cdb_buffer_id: Increment the buffer ID by 1 for each chunk sent 151287203Sken * down to the drive. 152287203Sken * 153287203Sken * inc_cdb_offset: Increment the offset field in the CDB with the byte 154287203Sken * offset into the firmware file. 155287203Sken * 156287203Sken * tur_status: Pay attention to whether the device is ready before 157287203Sken * upgrading the firmware, or not. See above for the 158287203Sken * values. 159287203Sken */ 160227961Semastestruct fw_vendor { 161227961Semaste fw_vendor_t type; 162227961Semaste const char *pattern; 163287203Sken int dev_type; 164227961Semaste int max_pkt_size; 165227961Semaste u_int8_t cdb_byte2; 166227961Semaste u_int8_t cdb_byte2_last; 167227961Semaste int inc_cdb_buffer_id; 168227961Semaste int inc_cdb_offset; 169287203Sken fw_tur_status tur_status; 170287203Sken int timeout_ms; 171287203Sken fw_timeout_type timeout_type; 172227961Semaste}; 173227961Semaste 174287203Sken/* 175287203Sken * Vendor notes: 176287203Sken * 177287203Sken * HGST: The packets need to be sent in multiples of 4K. 178287203Sken * 179287203Sken * IBM: For LTO and TS drives, the buffer ID is ignored in mode 7 (and 180287203Sken * some other modes). It treats the request as a firmware download. 181287203Sken * The offset (and therefore the length of each chunk sent) needs 182287203Sken * to be a multiple of the offset boundary specified for firmware 183287203Sken * (buffer ID 4) in the read buffer command. At least for LTO-6, 184287203Sken * that seems to be 0, but using a 32K chunk size should satisfy 185287203Sken * most any alignment requirement. 186287203Sken * 187287203Sken * SmrtStor: Mode 5 is also supported, but since the firmware is 400KB or 188287203Sken * so, we can't fit it in a single request in most cases. 189287203Sken */ 190287203Skenstatic struct fw_vendor vendors_list[] = { 191287203Sken {VENDOR_HGST, "HGST", T_DIRECT, 192287203Sken 0x1000, 0x07, 0x07, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 193287203Sken {VENDOR_HITACHI, "HITACHI", T_ANY, 194287203Sken 0x8000, 0x05, 0x05, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 195287203Sken {VENDOR_HP, "HP", T_ANY, 196287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 197287203Sken {VENDOR_IBM, "IBM", T_SEQUENTIAL, 198287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_NA, 300 * 1000, FW_TIMEOUT_DEFAULT}, 199287203Sken {VENDOR_IBM, "IBM", T_ANY, 200287203Sken 0x8000, 0x05, 0x05, 1, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 201287203Sken {VENDOR_PLEXTOR, "PLEXTOR", T_ANY, 202287203Sken 0x2000, 0x04, 0x05, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 203287203Sken {VENDOR_QUALSTAR, "QUALSTAR", T_ANY, 204287203Sken 0x2030, 0x05, 0x05, 0, 0, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 205287203Sken {VENDOR_QUANTUM, "QUANTUM", T_ANY, 206287203Sken 0x2000, 0x04, 0x05, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 207287203Sken {VENDOR_SAMSUNG, "SAMSUNG", T_ANY, 208287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 209287203Sken {VENDOR_SEAGATE, "SEAGATE", T_ANY, 210287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 211287203Sken {VENDOR_SMART, "SmrtStor", T_DIRECT, 212287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, FW_TIMEOUT_DEFAULT}, 213287203Sken 214287203Sken /* 215287203Sken * We match any ATA device. This is really just a placeholder, 216287203Sken * since we won't actually send a WRITE BUFFER with any of the 217287203Sken * listed parameters. If a SATA device is behind a SAS controller, 218287203Sken * the SCSI to ATA translation code (at least for LSI) doesn't 219287203Sken * generaly translate a SCSI WRITE BUFFER into an ATA DOWNLOAD 220287203Sken * MICROCODE command. So, we use the SCSI ATA PASS_THROUGH command 221287203Sken * to send the ATA DOWNLOAD MICROCODE command instead. 222287203Sken */ 223287203Sken {VENDOR_ATA, "ATA", T_ANY, 224287203Sken 0x8000, 0x07, 0x07, 0, 1, FW_TUR_READY, WB_TIMEOUT, 225287203Sken FW_TIMEOUT_NO_PROBE}, 226287203Sken {VENDOR_UNKNOWN, NULL, T_ANY, 227287203Sken 0x0000, 0x00, 0x00, 0, 0, FW_TUR_NONE, WB_TIMEOUT, FW_TIMEOUT_DEFAULT} 228227961Semaste}; 229227961Semaste 230287203Skenstruct fw_timeout_desc { 231287203Sken fw_timeout_type timeout_type; 232287203Sken const char *timeout_desc; 233287203Sken}; 234287203Sken 235287203Skenstatic const struct fw_timeout_desc fw_timeout_desc_table[] = { 236287203Sken { FW_TIMEOUT_DEFAULT, "the default" }, 237287203Sken { FW_TIMEOUT_DEV_REPORTED, "recommended by this particular device" }, 238287203Sken { FW_TIMEOUT_NO_PROBE, "the default" }, 239287203Sken { FW_TIMEOUT_USER_SPEC, "what was specified on the command line" } 240287203Sken}; 241287203Sken 242237281Sscottl#ifndef ATA_DOWNLOAD_MICROCODE 243237281Sscottl#define ATA_DOWNLOAD_MICROCODE 0x92 244237281Sscottl#endif 245237281Sscottl 246237281Sscottl#define USE_OFFSETS_FEATURE 0x3 247237281Sscottl 248237281Sscottl#ifndef LOW_SECTOR_SIZE 249237281Sscottl#define LOW_SECTOR_SIZE 512 250237281Sscottl#endif 251237281Sscottl 252237281Sscottl#define ATA_MAKE_LBA(o, p) \ 253237281Sscottl ((((((o) / LOW_SECTOR_SIZE) >> 8) & 0xff) << 16) | \ 254237281Sscottl ((((o) / LOW_SECTOR_SIZE) & 0xff) << 8) | \ 255237281Sscottl ((((p) / LOW_SECTOR_SIZE) >> 8) & 0xff)) 256237281Sscottl 257237281Sscottl#define ATA_MAKE_SECTORS(p) (((p) / 512) & 0xff) 258237281Sscottl 259237281Sscottl#ifndef UNKNOWN_MAX_PKT_SIZE 260237281Sscottl#define UNKNOWN_MAX_PKT_SIZE 0x8000 261237281Sscottl#endif 262237281Sscottl 263287203Skenstatic struct fw_vendor *fw_get_vendor(struct cam_device *cam_dev, 264287203Sken struct ata_params *ident_buf); 265287203Skenstatic int fw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, 266314221Sken int task_attr, int retry_count, int timeout); 267287203Skenstatic int fw_validate_ibm(struct cam_device *dev, int retry_count, 268287203Sken int timeout, int fd, char *buf, 269287203Sken const char *fw_img_path, int quiet); 270287203Skenstatic char *fw_read_img(struct cam_device *dev, int retry_count, 271287203Sken int timeout, int quiet, const char *fw_img_path, 272287203Sken struct fw_vendor *vp, int *num_bytes); 273287203Skenstatic int fw_check_device_ready(struct cam_device *dev, 274287203Sken camcontrol_devtype devtype, 275287203Sken struct fw_vendor *vp, int printerrors, 276287203Sken int timeout); 277287203Skenstatic int fw_download_img(struct cam_device *cam_dev, 278287203Sken struct fw_vendor *vp, char *buf, int img_size, 279287203Sken int sim_mode, int printerrors, int quiet, 280287203Sken int retry_count, int timeout, const char */*name*/, 281287203Sken camcontrol_devtype devtype); 282227961Semaste 283227961Semaste/* 284227961Semaste * Find entry in vendors list that belongs to 285227961Semaste * the vendor of given cam device. 286227961Semaste */ 287287203Skenstatic struct fw_vendor * 288287203Skenfw_get_vendor(struct cam_device *cam_dev, struct ata_params *ident_buf) 289227961Semaste{ 290287203Sken char vendor[42]; 291287203Sken struct fw_vendor *vp; 292227961Semaste 293227961Semaste if (cam_dev == NULL) 294227961Semaste return (NULL); 295287203Sken 296287203Sken if (ident_buf != NULL) { 297287203Sken cam_strvis((u_char *)vendor, ident_buf->model, 298287203Sken sizeof(ident_buf->model), sizeof(vendor)); 299287203Sken for (vp = vendors_list; vp->pattern != NULL; vp++) { 300287203Sken if (vp->type == VENDOR_ATA) 301287203Sken return (vp); 302287203Sken } 303287203Sken } else { 304287203Sken cam_strvis((u_char *)vendor, (u_char *)cam_dev->inq_data.vendor, 305287203Sken sizeof(cam_dev->inq_data.vendor), sizeof(vendor)); 306287203Sken } 307227961Semaste for (vp = vendors_list; vp->pattern != NULL; vp++) { 308227961Semaste if (!cam_strmatch((const u_char *)vendor, 309287203Sken (const u_char *)vp->pattern, strlen(vendor))) { 310287203Sken if ((vp->dev_type == T_ANY) 311287203Sken || (vp->dev_type == SID_TYPE(&cam_dev->inq_data))) 312287203Sken break; 313287203Sken } 314227961Semaste } 315227961Semaste return (vp); 316227961Semaste} 317227961Semaste 318287203Skenstatic int 319287203Skenfw_get_timeout(struct cam_device *cam_dev, struct fw_vendor *vp, 320314221Sken int task_attr, int retry_count, int timeout) 321287203Sken{ 322287203Sken struct scsi_report_supported_opcodes_one *one; 323287203Sken struct scsi_report_supported_opcodes_timeout *td; 324287203Sken uint8_t *buf = NULL; 325287203Sken uint32_t fill_len = 0, cdb_len = 0, rec_timeout = 0; 326287203Sken int retval = 0; 327287203Sken 328287203Sken /* 329287203Sken * If the user has specified a timeout on the command line, we let 330287203Sken * him override any default or probed value. 331287203Sken */ 332287203Sken if (timeout != 0) { 333287203Sken vp->timeout_type = FW_TIMEOUT_USER_SPEC; 334287203Sken vp->timeout_ms = timeout; 335287203Sken goto bailout; 336287203Sken } 337287203Sken 338287203Sken /* 339287203Sken * Check to see whether we should probe for a timeout for this 340287203Sken * device. 341287203Sken */ 342287203Sken if (vp->timeout_type == FW_TIMEOUT_NO_PROBE) 343287203Sken goto bailout; 344287203Sken 345287203Sken retval = scsigetopcodes(/*device*/ cam_dev, 346287203Sken /*opcode_set*/ 1, 347287203Sken /*opcode*/ WRITE_BUFFER, 348287203Sken /*show_sa_errors*/ 1, 349287203Sken /*sa_set*/ 0, 350287203Sken /*service_action*/ 0, 351287203Sken /*timeout_desc*/ 1, 352314221Sken /*task_attr*/ task_attr, 353287203Sken /*retry_count*/ retry_count, 354287203Sken /*timeout*/ 10000, 355287203Sken /*verbose*/ 0, 356287203Sken /*fill_len*/ &fill_len, 357287203Sken /*data_ptr*/ &buf); 358287203Sken /* 359287203Sken * It isn't an error if we can't get a timeout descriptor. We just 360287203Sken * continue on with the default timeout. 361287203Sken */ 362287203Sken if (retval != 0) { 363287203Sken retval = 0; 364287203Sken goto bailout; 365287203Sken } 366287203Sken 367287203Sken /* 368287203Sken * Even if the drive didn't return a SCSI error, if we don't have 369287203Sken * enough data to contain the one opcode descriptor, the CDB 370287203Sken * structure and a timeout descriptor, we don't have the timeout 371287203Sken * value we're looking for. So we'll just fall back to the 372287203Sken * default value. 373287203Sken */ 374287203Sken if (fill_len < (sizeof(*one) + sizeof(struct scsi_write_buffer) + 375287203Sken sizeof(*td))) 376287203Sken goto bailout; 377287203Sken 378287203Sken one = (struct scsi_report_supported_opcodes_one *)buf; 379287203Sken 380287203Sken /* 381287203Sken * If the drive claims to not support the WRITE BUFFER command... 382287203Sken * fall back to the default timeout value and let things fail on 383287203Sken * the actual firmware download. 384287203Sken */ 385287203Sken if ((one->support & RSO_ONE_SUP_MASK) == RSO_ONE_SUP_NOT_SUP) 386287203Sken goto bailout; 387287203Sken 388287203Sken cdb_len = scsi_2btoul(one->cdb_length); 389287203Sken td = (struct scsi_report_supported_opcodes_timeout *) 390287203Sken &buf[sizeof(*one) + cdb_len]; 391287203Sken 392287203Sken rec_timeout = scsi_4btoul(td->recommended_time); 393287203Sken /* 394287203Sken * If the recommended timeout is 0, then the device has probably 395287203Sken * returned a bogus value. 396287203Sken */ 397287203Sken if (rec_timeout == 0) 398287203Sken goto bailout; 399287203Sken 400287203Sken /* CAM timeouts are in ms */ 401287203Sken rec_timeout *= 1000; 402287203Sken 403287203Sken vp->timeout_ms = rec_timeout; 404287203Sken vp->timeout_type = FW_TIMEOUT_DEV_REPORTED; 405287203Sken 406287203Skenbailout: 407287203Sken return (retval); 408287203Sken} 409287203Sken 410287203Sken#define SVPD_IBM_FW_DESIGNATION 0x03 411287203Sken 412227961Semaste/* 413287203Sken * IBM LTO and TS tape drives have an INQUIRY VPD page 0x3 with the following 414287203Sken * format: 415287203Sken */ 416287203Skenstruct fw_ibm_tape_fw_designation { 417287203Sken uint8_t device; 418287203Sken uint8_t page_code; 419287203Sken uint8_t reserved; 420287203Sken uint8_t length; 421287203Sken uint8_t ascii_length; 422287203Sken uint8_t reserved2[3]; 423287203Sken uint8_t load_id[4]; 424287203Sken uint8_t fw_rev[4]; 425287203Sken uint8_t ptf_number[4]; 426287203Sken uint8_t patch_number[4]; 427287203Sken uint8_t ru_name[8]; 428287203Sken uint8_t lib_seq_num[5]; 429287203Sken}; 430287203Sken 431287203Sken/* 432287203Sken * The firmware for IBM tape drives has the following header format. The 433287203Sken * load_id and ru_name in the header file should match what is returned in 434287203Sken * VPD page 0x3. 435287203Sken */ 436287203Skenstruct fw_ibm_tape_fw_header { 437287203Sken uint8_t unspec[4]; 438287203Sken uint8_t length[4]; /* Firmware and header! */ 439287203Sken uint8_t load_id[4]; 440287203Sken uint8_t fw_rev[4]; 441287203Sken uint8_t reserved[8]; 442287203Sken uint8_t ru_name[8]; 443287203Sken}; 444287203Sken 445287203Skenstatic int 446287203Skenfw_validate_ibm(struct cam_device *dev, int retry_count, int timeout, int fd, 447287203Sken char *buf, const char *fw_img_path, int quiet) 448287203Sken{ 449287203Sken union ccb *ccb; 450287203Sken struct fw_ibm_tape_fw_designation vpd_page; 451287203Sken struct fw_ibm_tape_fw_header *header; 452287203Sken char drive_rev[sizeof(vpd_page.fw_rev) + 1]; 453287203Sken char file_rev[sizeof(vpd_page.fw_rev) + 1]; 454287203Sken int retval = 1; 455287203Sken 456287203Sken ccb = cam_getccb(dev); 457287203Sken if (ccb == NULL) { 458287203Sken warnx("couldn't allocate CCB"); 459287203Sken goto bailout; 460287203Sken } 461287203Sken 462287203Sken /* cam_getccb cleans up the header, caller has to zero the payload */ 463302377Struckman CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 464287203Sken 465287203Sken bzero(&vpd_page, sizeof(vpd_page)); 466287203Sken 467287203Sken scsi_inquiry(&ccb->csio, 468287203Sken /*retries*/ retry_count, 469287203Sken /*cbfcnp*/ NULL, 470287203Sken /* tag_action */ MSG_SIMPLE_Q_TAG, 471287203Sken /* inq_buf */ (u_int8_t *)&vpd_page, 472287203Sken /* inq_len */ sizeof(vpd_page), 473287203Sken /* evpd */ 1, 474287203Sken /* page_code */ SVPD_IBM_FW_DESIGNATION, 475287203Sken /* sense_len */ SSD_FULL_SIZE, 476287203Sken /* timeout */ timeout ? timeout : 5000); 477287203Sken 478287203Sken /* Disable freezing the device queue */ 479287203Sken ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 480287203Sken 481287203Sken if (retry_count != 0) 482287203Sken ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER; 483287203Sken 484287203Sken if (cam_send_ccb(dev, ccb) < 0) { 485287203Sken warn("error getting firmware designation page"); 486287203Sken 487287203Sken cam_error_print(dev, ccb, CAM_ESF_ALL, 488287203Sken CAM_EPF_ALL, stderr); 489287203Sken 490287203Sken cam_freeccb(ccb); 491301788Sngie ccb = NULL; 492287203Sken goto bailout; 493287203Sken } 494287203Sken 495287203Sken if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) { 496287203Sken cam_error_print(dev, ccb, CAM_ESF_ALL, 497287203Sken CAM_EPF_ALL, stderr); 498287203Sken goto bailout; 499287203Sken } 500287203Sken 501287203Sken /* 502287203Sken * Read the firmware header only. 503287203Sken */ 504287203Sken if (read(fd, buf, sizeof(*header)) != sizeof(*header)) { 505287203Sken warn("unable to read %zu bytes from %s", sizeof(*header), 506287203Sken fw_img_path); 507287203Sken goto bailout; 508287203Sken } 509287203Sken 510287203Sken /* Rewind the file back to 0 for the full file read. */ 511287203Sken if (lseek(fd, 0, SEEK_SET) == -1) { 512287203Sken warn("Unable to lseek"); 513287203Sken goto bailout; 514287203Sken } 515287203Sken 516287203Sken header = (struct fw_ibm_tape_fw_header *)buf; 517287203Sken 518287203Sken bzero(drive_rev, sizeof(drive_rev)); 519287203Sken bcopy(vpd_page.fw_rev, drive_rev, sizeof(vpd_page.fw_rev)); 520287203Sken bzero(file_rev, sizeof(file_rev)); 521287203Sken bcopy(header->fw_rev, file_rev, sizeof(header->fw_rev)); 522287203Sken 523287203Sken if (quiet == 0) { 524287203Sken fprintf(stdout, "Current Drive Firmware version: %s\n", 525287203Sken drive_rev); 526287203Sken fprintf(stdout, "Firmware File version: %s\n", file_rev); 527287203Sken } 528287203Sken 529287203Sken /* 530287203Sken * For IBM tape drives the load ID and RU name reported by the 531287203Sken * drive should match what is in the firmware file. 532287203Sken */ 533287203Sken if (bcmp(vpd_page.load_id, header->load_id, 534287203Sken MIN(sizeof(vpd_page.load_id), sizeof(header->load_id))) != 0) { 535287203Sken warnx("Drive Firmware load ID 0x%x does not match firmware " 536287203Sken "file load ID 0x%x", scsi_4btoul(vpd_page.load_id), 537287203Sken scsi_4btoul(header->load_id)); 538287203Sken goto bailout; 539287203Sken } 540287203Sken 541287203Sken if (bcmp(vpd_page.ru_name, header->ru_name, 542287203Sken MIN(sizeof(vpd_page.ru_name), sizeof(header->ru_name))) != 0) { 543287203Sken warnx("Drive Firmware RU name 0x%jx does not match firmware " 544287203Sken "file RU name 0x%jx", 545287203Sken (uintmax_t)scsi_8btou64(vpd_page.ru_name), 546287203Sken (uintmax_t)scsi_8btou64(header->ru_name)); 547287203Sken goto bailout; 548287203Sken } 549287203Sken if (quiet == 0) 550287203Sken fprintf(stdout, "Firmware file is valid for this drive.\n"); 551287203Sken retval = 0; 552287203Skenbailout: 553319266Sasomers cam_freeccb(ccb); 554287203Sken 555287203Sken return (retval); 556287203Sken} 557287203Sken 558287203Sken/* 559227961Semaste * Allocate a buffer and read fw image file into it 560227961Semaste * from given path. Number of bytes read is stored 561227961Semaste * in num_bytes. 562227961Semaste */ 563227961Semastestatic char * 564287203Skenfw_read_img(struct cam_device *dev, int retry_count, int timeout, int quiet, 565287203Sken const char *fw_img_path, struct fw_vendor *vp, int *num_bytes) 566227961Semaste{ 567227961Semaste int fd; 568227961Semaste struct stat stbuf; 569227961Semaste char *buf; 570227961Semaste off_t img_size; 571227961Semaste int skip_bytes = 0; 572227961Semaste 573227961Semaste if ((fd = open(fw_img_path, O_RDONLY)) < 0) { 574227961Semaste warn("Could not open image file %s", fw_img_path); 575227961Semaste return (NULL); 576227961Semaste } 577227961Semaste if (fstat(fd, &stbuf) < 0) { 578227961Semaste warn("Could not stat image file %s", fw_img_path); 579227961Semaste goto bailout1; 580227961Semaste } 581227961Semaste if ((img_size = stbuf.st_size) == 0) { 582227961Semaste warnx("Zero length image file %s", fw_img_path); 583227961Semaste goto bailout1; 584227961Semaste } 585227961Semaste if ((buf = malloc(img_size)) == NULL) { 586227961Semaste warnx("Could not allocate buffer to read image file %s", 587227961Semaste fw_img_path); 588227961Semaste goto bailout1; 589227961Semaste } 590227961Semaste /* Skip headers if applicable. */ 591227961Semaste switch (vp->type) { 592227961Semaste case VENDOR_SEAGATE: 593227961Semaste if (read(fd, buf, 16) != 16) { 594227961Semaste warn("Could not read image file %s", fw_img_path); 595227961Semaste goto bailout; 596227961Semaste } 597227961Semaste if (lseek(fd, 0, SEEK_SET) == -1) { 598227961Semaste warn("Unable to lseek"); 599227961Semaste goto bailout; 600227961Semaste } 601227961Semaste if ((strncmp(buf, "SEAGATE,SEAGATE ", 16) == 0) || 602227961Semaste (img_size % 512 == 80)) 603227961Semaste skip_bytes = 80; 604227961Semaste break; 605237281Sscottl case VENDOR_QUALSTAR: 606237281Sscottl skip_bytes = img_size % 1030; 607237281Sscottl break; 608287203Sken case VENDOR_IBM: { 609287203Sken if (vp->dev_type != T_SEQUENTIAL) 610287203Sken break; 611287203Sken if (fw_validate_ibm(dev, retry_count, timeout, fd, buf, 612287203Sken fw_img_path, quiet) != 0) 613287203Sken goto bailout; 614287203Sken break; 615287203Sken } 616227961Semaste default: 617227961Semaste break; 618227961Semaste } 619227961Semaste if (skip_bytes != 0) { 620227961Semaste fprintf(stdout, "Skipping %d byte header.\n", skip_bytes); 621227961Semaste if (lseek(fd, skip_bytes, SEEK_SET) == -1) { 622227961Semaste warn("Could not lseek"); 623227961Semaste goto bailout; 624227961Semaste } 625227961Semaste img_size -= skip_bytes; 626227961Semaste } 627227961Semaste /* Read image into a buffer. */ 628227961Semaste if (read(fd, buf, img_size) != img_size) { 629227961Semaste warn("Could not read image file %s", fw_img_path); 630227961Semaste goto bailout; 631227961Semaste } 632227961Semaste *num_bytes = img_size; 633256113Semaste close(fd); 634227961Semaste return (buf); 635227961Semastebailout: 636227961Semaste free(buf); 637227961Semastebailout1: 638227961Semaste close(fd); 639227961Semaste *num_bytes = 0; 640227961Semaste return (NULL); 641227961Semaste} 642227961Semaste 643287203Sken/* 644287203Sken * Returns 0 for "success", where success means that the device has met the 645287203Sken * requirement in the vendor structure for being ready or not ready when 646287203Sken * firmware is downloaded. 647287203Sken * 648287203Sken * Returns 1 for a failure to be ready to accept a firmware download. 649287203Sken * (e.g., a drive needs to be ready, but returns not ready) 650287203Sken * 651287203Sken * Returns -1 for any other failure. 652287203Sken */ 653287203Skenstatic int 654287203Skenfw_check_device_ready(struct cam_device *dev, camcontrol_devtype devtype, 655287203Sken struct fw_vendor *vp, int printerrors, int timeout) 656287203Sken{ 657287203Sken union ccb *ccb; 658287203Sken int retval = 0; 659287203Sken int16_t *ptr = NULL; 660287203Sken size_t dxfer_len = 0; 661287203Sken 662287203Sken if ((ccb = cam_getccb(dev)) == NULL) { 663287203Sken warnx("Could not allocate CCB"); 664287203Sken retval = -1; 665287203Sken goto bailout; 666287203Sken } 667287203Sken 668302377Struckman CCB_CLEAR_ALL_EXCEPT_HDR(ccb); 669287203Sken 670287203Sken if (devtype != CC_DT_SCSI) { 671287203Sken dxfer_len = sizeof(struct ata_params); 672287203Sken 673287203Sken ptr = (uint16_t *)malloc(dxfer_len); 674287203Sken if (ptr == NULL) { 675287203Sken warnx("can't malloc memory for identify"); 676287203Sken retval = -1; 677287203Sken goto bailout; 678287203Sken } 679287203Sken bzero(ptr, dxfer_len); 680287203Sken } 681287203Sken 682287203Sken switch (devtype) { 683287203Sken case CC_DT_SCSI: 684287203Sken scsi_test_unit_ready(&ccb->csio, 685287203Sken /*retries*/ 0, 686287203Sken /*cbfcnp*/ NULL, 687287203Sken /*tag_action*/ MSG_SIMPLE_Q_TAG, 688287203Sken /*sense_len*/ SSD_FULL_SIZE, 689287203Sken /*timeout*/ 5000); 690287203Sken break; 691287203Sken case CC_DT_ATA_BEHIND_SCSI: 692287203Sken case CC_DT_ATA: { 693287203Sken build_ata_cmd(ccb, 694287203Sken /*retries*/ 1, 695287203Sken /*flags*/ CAM_DIR_IN, 696287203Sken /*tag_action*/ MSG_SIMPLE_Q_TAG, 697287203Sken /*protocol*/ AP_PROTO_PIO_IN, 698287203Sken /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES | 699287203Sken AP_FLAG_TLEN_SECT_CNT | 700287203Sken AP_FLAG_TDIR_FROM_DEV, 701287203Sken /*features*/ 0, 702287203Sken /*sector_count*/ (uint8_t) dxfer_len, 703287203Sken /*lba*/ 0, 704287203Sken /*command*/ ATA_ATA_IDENTIFY, 705287203Sken /*data_ptr*/ (uint8_t *)ptr, 706287203Sken /*dxfer_len*/ dxfer_len, 707287203Sken /*sense_len*/ SSD_FULL_SIZE, 708287203Sken /*timeout*/ timeout ? timeout : 30 * 1000, 709287203Sken /*is48bit*/ 0, 710287203Sken /*devtype*/ devtype); 711287203Sken break; 712287203Sken } 713287203Sken default: 714287203Sken warnx("Unknown disk type %d", devtype); 715287203Sken retval = -1; 716287203Sken goto bailout; 717287203Sken break; /*NOTREACHED*/ 718287203Sken } 719287203Sken 720287203Sken ccb->ccb_h.flags |= CAM_DEV_QFRZDIS; 721287203Sken 722287203Sken retval = cam_send_ccb(dev, ccb); 723287203Sken if (retval != 0) { 724287203Sken warn("error sending %s CCB", (devtype == CC_DT_SCSI) ? 725287203Sken "Test Unit Ready" : "Identify"); 726287203Sken retval = -1; 727287203Sken goto bailout; 728287203Sken } 729287203Sken 730287203Sken if (((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) 731287203Sken && (vp->tur_status == FW_TUR_READY)) { 732287203Sken warnx("Device is not ready"); 733287203Sken if (printerrors) 734287203Sken cam_error_print(dev, ccb, CAM_ESF_ALL, 735287203Sken CAM_EPF_ALL, stderr); 736287203Sken retval = 1; 737287203Sken goto bailout; 738287203Sken } else if (((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) 739287203Sken && (vp->tur_status == FW_TUR_NOT_READY)) { 740287203Sken warnx("Device cannot have media loaded when firmware is " 741287203Sken "downloaded"); 742287203Sken retval = 1; 743287203Sken goto bailout; 744287203Sken } 745287203Skenbailout: 746319266Sasomers free(ptr); 747319266Sasomers cam_freeccb(ccb); 748287203Sken 749287203Sken return (retval); 750287203Sken} 751287203Sken 752227961Semaste/* 753227961Semaste * Download firmware stored in buf to cam_dev. If simulation mode 754227961Semaste * is enabled, only show what packet sizes would be sent to the 755227961Semaste * device but do not sent any actual packets 756227961Semaste */ 757227961Semastestatic int 758287203Skenfw_download_img(struct cam_device *cam_dev, struct fw_vendor *vp, 759287203Sken char *buf, int img_size, int sim_mode, int printerrors, int quiet, 760287203Sken int retry_count, int timeout, const char *imgname, 761287203Sken camcontrol_devtype devtype) 762227961Semaste{ 763227961Semaste struct scsi_write_buffer cdb; 764237281Sscottl progress_t progress; 765287203Sken int size = 0; 766287203Sken union ccb *ccb = NULL; 767227961Semaste int pkt_count = 0; 768237281Sscottl int max_pkt_size; 769227961Semaste u_int32_t pkt_size = 0; 770227961Semaste char *pkt_ptr = buf; 771227961Semaste u_int32_t offset; 772227961Semaste int last_pkt = 0; 773287203Sken int retval = 0; 774227961Semaste 775287203Sken /* 776287203Sken * Check to see whether the device is ready to accept a firmware 777287203Sken * download. 778287203Sken */ 779287203Sken retval = fw_check_device_ready(cam_dev, devtype, vp, printerrors, 780287203Sken timeout); 781287203Sken if (retval != 0) 782287203Sken goto bailout; 783287203Sken 784227961Semaste if ((ccb = cam_getccb(cam_dev)) == NULL) { 785227961Semaste warnx("Could not allocate CCB"); 786287203Sken retval = 1; 787287203Sken goto bailout; 788227961Semaste } 789237281Sscottl 790302377Struckman CCB_CLEAR_ALL_EXCEPT_HDR(ccb); 791237281Sscottl 792237281Sscottl max_pkt_size = vp->max_pkt_size; 793287203Sken if (max_pkt_size == 0) 794237281Sscottl max_pkt_size = UNKNOWN_MAX_PKT_SIZE; 795287203Sken 796287203Sken pkt_size = max_pkt_size; 797237281Sscottl progress_init(&progress, imgname, size = img_size); 798227961Semaste /* Download single fw packets. */ 799227961Semaste do { 800237281Sscottl if (img_size <= max_pkt_size) { 801227961Semaste last_pkt = 1; 802227961Semaste pkt_size = img_size; 803227961Semaste } 804237281Sscottl progress_update(&progress, size - img_size); 805287203Sken if (((sim_mode == 0) && (quiet == 0)) 806287203Sken || ((sim_mode != 0) && (printerrors == 0))) 807287203Sken progress_draw(&progress); 808227961Semaste bzero(&cdb, sizeof(cdb)); 809287203Sken switch (devtype) { 810287203Sken case CC_DT_SCSI: 811237281Sscottl cdb.opcode = WRITE_BUFFER; 812237281Sscottl cdb.control = 0; 813237281Sscottl /* Parameter list length. */ 814237281Sscottl scsi_ulto3b(pkt_size, &cdb.length[0]); 815237281Sscottl offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0; 816237281Sscottl scsi_ulto3b(offset, &cdb.offset[0]); 817287203Sken cdb.byte2 = last_pkt ? vp->cdb_byte2_last : 818287203Sken vp->cdb_byte2; 819237281Sscottl cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0; 820237281Sscottl /* Zero out payload of ccb union after ccb header. */ 821302377Struckman CCB_CLEAR_ALL_EXCEPT_HDR(&ccb->csio); 822287203Sken /* 823287203Sken * Copy previously constructed cdb into ccb_scsiio 824287203Sken * struct. 825287203Sken */ 826237281Sscottl bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0], 827237281Sscottl sizeof(struct scsi_write_buffer)); 828237281Sscottl /* Fill rest of ccb_scsiio struct. */ 829287203Sken cam_fill_csio(&ccb->csio, /* ccb_scsiio*/ 830287203Sken retry_count, /* retries*/ 831287203Sken NULL, /* cbfcnp*/ 832287203Sken CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags*/ 833287203Sken CAM_TAG_ACTION_NONE, /* tag_action*/ 834287203Sken (u_char *)pkt_ptr, /* data_ptr*/ 835287203Sken pkt_size, /* dxfer_len*/ 836287203Sken SSD_FULL_SIZE, /* sense_len*/ 837287203Sken sizeof(struct scsi_write_buffer), /* cdb_len*/ 838287203Sken timeout ? timeout : WB_TIMEOUT); /* timeout*/ 839287203Sken break; 840287203Sken case CC_DT_ATA: 841287203Sken case CC_DT_ATA_BEHIND_SCSI: { 842287203Sken uint32_t off; 843237281Sscottl 844287203Sken off = (uint32_t)(pkt_ptr - buf); 845287203Sken 846287203Sken build_ata_cmd(ccb, 847287203Sken /*retry_count*/ retry_count, 848287203Sken /*flags*/ CAM_DIR_OUT | CAM_DEV_QFRZDIS, 849287203Sken /*tag_action*/ CAM_TAG_ACTION_NONE, 850287203Sken /*protocol*/ AP_PROTO_PIO_OUT, 851287203Sken /*ata_flags*/ AP_FLAG_BYT_BLOK_BYTES | 852287203Sken AP_FLAG_TLEN_SECT_CNT | 853287203Sken AP_FLAG_TDIR_TO_DEV, 854287203Sken /*features*/ USE_OFFSETS_FEATURE, 855287203Sken /*sector_count*/ ATA_MAKE_SECTORS(pkt_size), 856287203Sken /*lba*/ ATA_MAKE_LBA(off, pkt_size), 857287203Sken /*command*/ ATA_DOWNLOAD_MICROCODE, 858287203Sken /*data_ptr*/ (uint8_t *)pkt_ptr, 859287203Sken /*dxfer_len*/ pkt_size, 860287203Sken /*sense_len*/ SSD_FULL_SIZE, 861287203Sken /*timeout*/ timeout ? timeout : WB_TIMEOUT, 862287203Sken /*is48bit*/ 0, 863287203Sken /*devtype*/ devtype); 864287203Sken break; 865237281Sscottl } 866287203Sken default: 867287203Sken warnx("Unknown device type %d", devtype); 868287203Sken retval = 1; 869287203Sken goto bailout; 870287203Sken break; /*NOTREACHED*/ 871287203Sken } 872227961Semaste if (!sim_mode) { 873227961Semaste /* Execute the command. */ 874251743Smav if (cam_send_ccb(cam_dev, ccb) < 0 || 875251743Smav (ccb->ccb_h.status & CAM_STATUS_MASK) != 876251743Smav CAM_REQ_CMP) { 877227961Semaste warnx("Error writing image to device"); 878241737Sed if (printerrors) 879287203Sken cam_error_print(cam_dev, ccb, 880287203Sken CAM_ESF_ALL, CAM_EPF_ALL, stderr); 881287203Sken retval = 1; 882227961Semaste goto bailout; 883227961Semaste } 884287203Sken } else if (printerrors) { 885287203Sken cam_error_print(cam_dev, ccb, CAM_ESF_COMMAND, 0, 886287203Sken stdout); 887227961Semaste } 888287203Sken 889227961Semaste /* Prepare next round. */ 890227961Semaste pkt_count++; 891227961Semaste pkt_ptr += pkt_size; 892227961Semaste img_size -= pkt_size; 893227961Semaste } while(!last_pkt); 894227961Semastebailout: 895287203Sken if (quiet == 0) 896287203Sken progress_complete(&progress, size - img_size); 897319266Sasomers cam_freeccb(ccb); 898287203Sken return (retval); 899227961Semaste} 900227961Semaste 901227961Semasteint 902227961Semastefwdownload(struct cam_device *device, int argc, char **argv, 903314221Sken char *combinedopt, int printerrors, int task_attr, int retry_count, 904314221Sken int timeout) 905227961Semaste{ 906319266Sasomers union ccb *ccb = NULL; 907287203Sken struct fw_vendor *vp; 908227961Semaste char *fw_img_path = NULL; 909287203Sken struct ata_params *ident_buf = NULL; 910287203Sken camcontrol_devtype devtype; 911287203Sken char *buf = NULL; 912227961Semaste int img_size; 913227961Semaste int c; 914227961Semaste int sim_mode = 0; 915227961Semaste int confirmed = 0; 916287203Sken int quiet = 0; 917287203Sken int retval = 0; 918227961Semaste 919227961Semaste while ((c = getopt(argc, argv, combinedopt)) != -1) { 920227961Semaste switch (c) { 921287203Sken case 'f': 922287203Sken fw_img_path = optarg; 923287203Sken break; 924287203Sken case 'q': 925287203Sken quiet = 1; 926287203Sken break; 927227961Semaste case 's': 928227961Semaste sim_mode = 1; 929227961Semaste break; 930227961Semaste case 'y': 931227961Semaste confirmed = 1; 932227961Semaste break; 933227961Semaste default: 934227961Semaste break; 935227961Semaste } 936227961Semaste } 937227961Semaste 938227961Semaste if (fw_img_path == NULL) 939287203Sken errx(1, "you must specify a firmware image file using -f " 940287203Sken "option"); 941227961Semaste 942287203Sken retval = get_device_type(device, retry_count, timeout, printerrors, 943287203Sken &devtype); 944287203Sken if (retval != 0) 945287203Sken errx(1, "Unable to determine device type"); 946227961Semaste 947287203Sken if ((devtype == CC_DT_ATA) 948287203Sken || (devtype == CC_DT_ATA_BEHIND_SCSI)) { 949287203Sken ccb = cam_getccb(device); 950287203Sken if (ccb == NULL) { 951287203Sken warnx("couldn't allocate CCB"); 952287203Sken retval = 1; 953287203Sken goto bailout; 954287203Sken } 955287203Sken 956287203Sken if (ata_do_identify(device, retry_count, timeout, ccb, 957287203Sken &ident_buf) != 0) { 958287203Sken retval = 1; 959287203Sken goto bailout; 960287203Sken } 961287203Sken } else if (devtype != CC_DT_SCSI) 962287203Sken errx(1, "Unsupported device type %d", devtype); 963287203Sken 964287203Sken vp = fw_get_vendor(device, ident_buf); 965287203Sken /* 966287203Sken * Bail out if we have an unknown vendor and this isn't an ATA 967287203Sken * disk. For a SCSI disk, we have no chance of working properly 968287203Sken * with the default values in the VENDOR_UNKNOWN case. For an ATA 969287203Sken * disk connected via an ATA transport, we may work for drives that 970287203Sken * support the ATA_DOWNLOAD_MICROCODE command. 971287203Sken */ 972287203Sken if (((vp == NULL) 973287203Sken || (vp->type == VENDOR_UNKNOWN)) 974287203Sken && (devtype == CC_DT_SCSI)) 975287203Sken errx(1, "Unsupported device"); 976287203Sken 977314221Sken retval = fw_get_timeout(device, vp, task_attr, retry_count, timeout); 978287203Sken if (retval != 0) { 979287203Sken warnx("Unable to get a firmware download timeout value"); 980287203Sken goto bailout; 981287203Sken } 982287203Sken 983287203Sken buf = fw_read_img(device, retry_count, timeout, quiet, fw_img_path, 984287203Sken vp, &img_size); 985287203Sken if (buf == NULL) { 986287203Sken retval = 1; 987287203Sken goto bailout; 988287203Sken } 989287203Sken 990227961Semaste if (!confirmed) { 991227961Semaste fprintf(stdout, "You are about to download firmware image (%s)" 992227961Semaste " into the following device:\n", 993227961Semaste fw_img_path); 994287203Sken if (devtype == CC_DT_SCSI) { 995314221Sken if (scsidoinquiry(device, argc, argv, combinedopt, 996314221Sken MSG_SIMPLE_Q_TAG, 0, 5000) != 0) { 997287203Sken warnx("Error sending inquiry"); 998287203Sken retval = 1; 999287203Sken goto bailout; 1000287203Sken } 1001287203Sken } else { 1002287203Sken printf("%s%d: ", device->device_name, 1003287203Sken device->dev_unit_num); 1004287203Sken ata_print_ident(ident_buf); 1005287203Sken camxferrate(device); 1006287203Sken free(ident_buf); 1007287203Sken } 1008287203Sken fprintf(stdout, "Using a timeout of %u ms, which is %s.\n", 1009287203Sken vp->timeout_ms, 1010287203Sken fw_timeout_desc_table[vp->timeout_type].timeout_desc); 1011227961Semaste fprintf(stdout, "\nIt may damage your drive. "); 1012287203Sken if (!get_confirmation()) { 1013287203Sken retval = 1; 1014287203Sken goto bailout; 1015287203Sken } 1016227961Semaste } 1017287203Sken if ((sim_mode != 0) && (quiet == 0)) 1018227961Semaste fprintf(stdout, "Running in simulation mode\n"); 1019227961Semaste 1020241737Sed if (fw_download_img(device, vp, buf, img_size, sim_mode, printerrors, 1021287203Sken quiet, retry_count, vp->timeout_ms, fw_img_path, devtype) != 0) { 1022227961Semaste fprintf(stderr, "Firmware download failed\n"); 1023287203Sken retval = 1; 1024287203Sken goto bailout; 1025287203Sken } else if (quiet == 0) 1026227961Semaste fprintf(stdout, "Firmware download successful\n"); 1027227961Semaste 1028287203Skenbailout: 1029319266Sasomers cam_freeccb(ccb); 1030227961Semaste free(buf); 1031287203Sken return (retval); 1032227961Semaste} 1033227961Semaste 1034