fwdownload.c (8fa0b743820f61c661ba5f3ea0e3be0dc137910e) fwdownload.c (3ff78f821849dc402ff146f1cc7b34757b1810d0)
1/*-
2 * Copyright (c) 2011 Sandvine Incorporated. All rights reserved.
3 * Copyright (c) 2002-2011 Andre Albsmeier <andre@albsmeier.net>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 50 unchanged lines hidden (view full) ---

59#include <stdlib.h>
60#include <string.h>
61#include <unistd.h>
62
63#include <cam/scsi/scsi_all.h>
64#include <cam/scsi/scsi_message.h>
65#include <camlib.h>
66
1/*-
2 * Copyright (c) 2011 Sandvine Incorporated. All rights reserved.
3 * Copyright (c) 2002-2011 Andre Albsmeier <andre@albsmeier.net>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 50 unchanged lines hidden (view full) ---

59#include <stdlib.h>
60#include <string.h>
61#include <unistd.h>
62
63#include <cam/scsi/scsi_all.h>
64#include <cam/scsi/scsi_message.h>
65#include <camlib.h>
66
67#include "progress.h"
68
67#include "camcontrol.h"
68
69#define CMD_TIMEOUT 50000 /* 50 seconds */
70
71typedef enum {
72 VENDOR_HITACHI,
73 VENDOR_HP,
74 VENDOR_IBM,
75 VENDOR_PLEXTOR,
69#include "camcontrol.h"
70
71#define CMD_TIMEOUT 50000 /* 50 seconds */
72
73typedef enum {
74 VENDOR_HITACHI,
75 VENDOR_HP,
76 VENDOR_IBM,
77 VENDOR_PLEXTOR,
78 VENDOR_QUALSTAR,
76 VENDOR_QUANTUM,
77 VENDOR_SEAGATE,
78 VENDOR_UNKNOWN
79} fw_vendor_t;
80
81struct fw_vendor {
82 fw_vendor_t type;
83 const char *pattern;

--- 4 unchanged lines hidden (view full) ---

88 int inc_cdb_offset;
89};
90
91static const struct fw_vendor vendors_list[] = {
92 {VENDOR_HITACHI, "HITACHI", 0x8000, 0x05, 0x05, 1, 0},
93 {VENDOR_HP, "HP", 0x8000, 0x07, 0x07, 0, 1},
94 {VENDOR_IBM, "IBM", 0x8000, 0x05, 0x05, 1, 0},
95 {VENDOR_PLEXTOR, "PLEXTOR", 0x2000, 0x04, 0x05, 0, 1},
79 VENDOR_QUANTUM,
80 VENDOR_SEAGATE,
81 VENDOR_UNKNOWN
82} fw_vendor_t;
83
84struct fw_vendor {
85 fw_vendor_t type;
86 const char *pattern;

--- 4 unchanged lines hidden (view full) ---

91 int inc_cdb_offset;
92};
93
94static const struct fw_vendor vendors_list[] = {
95 {VENDOR_HITACHI, "HITACHI", 0x8000, 0x05, 0x05, 1, 0},
96 {VENDOR_HP, "HP", 0x8000, 0x07, 0x07, 0, 1},
97 {VENDOR_IBM, "IBM", 0x8000, 0x05, 0x05, 1, 0},
98 {VENDOR_PLEXTOR, "PLEXTOR", 0x2000, 0x04, 0x05, 0, 1},
99 {VENDOR_QUALSTAR, "QUALSTAR", 0x2030, 0x05, 0x05, 0, 0},
96 {VENDOR_QUANTUM, "QUANTUM", 0x2000, 0x04, 0x05, 0, 1},
97 {VENDOR_SEAGATE, "SEAGATE", 0x8000, 0x07, 0x07, 0, 1},
100 {VENDOR_QUANTUM, "QUANTUM", 0x2000, 0x04, 0x05, 0, 1},
101 {VENDOR_SEAGATE, "SEAGATE", 0x8000, 0x07, 0x07, 0, 1},
102 /* the next 2 are SATA disks going through SAS HBA */
103 {VENDOR_SEAGATE, "ATA ST", 0x8000, 0x07, 0x07, 0, 1},
104 {VENDOR_HITACHI, "ATA HDS", 0x8000, 0x05, 0x05, 1, 0},
98 {VENDOR_UNKNOWN, NULL, 0x0000, 0x00, 0x00, 0, 0}
99};
100
105 {VENDOR_UNKNOWN, NULL, 0x0000, 0x00, 0x00, 0, 0}
106};
107
108#ifndef ATA_DOWNLOAD_MICROCODE
109#define ATA_DOWNLOAD_MICROCODE 0x92
110#endif
111
112#define USE_OFFSETS_FEATURE 0x3
113
114#ifndef LOW_SECTOR_SIZE
115#define LOW_SECTOR_SIZE 512
116#endif
117
118#define ATA_MAKE_LBA(o, p) \
119 ((((((o) / LOW_SECTOR_SIZE) >> 8) & 0xff) << 16) | \
120 ((((o) / LOW_SECTOR_SIZE) & 0xff) << 8) | \
121 ((((p) / LOW_SECTOR_SIZE) >> 8) & 0xff))
122
123#define ATA_MAKE_SECTORS(p) (((p) / 512) & 0xff)
124
125#ifndef UNKNOWN_MAX_PKT_SIZE
126#define UNKNOWN_MAX_PKT_SIZE 0x8000
127#endif
128
101static const struct fw_vendor *fw_get_vendor(struct cam_device *cam_dev);
102static char *fw_read_img(const char *fw_img_path,
103 const struct fw_vendor *vp, int *num_bytes);
104static int fw_download_img(struct cam_device *cam_dev,
105 const struct fw_vendor *vp, char *buf, int img_size,
129static const struct fw_vendor *fw_get_vendor(struct cam_device *cam_dev);
130static char *fw_read_img(const char *fw_img_path,
131 const struct fw_vendor *vp, int *num_bytes);
132static int fw_download_img(struct cam_device *cam_dev,
133 const struct fw_vendor *vp, char *buf, int img_size,
106 int sim_mode, int verbose, int retry_count, int timeout);
134 int sim_mode, int verbose, int retry_count, int timeout,
135 const char */*name*/, const char */*type*/);
107
108/*
109 * Find entry in vendors list that belongs to
110 * the vendor of given cam device.
111 */
112static const struct fw_vendor *
113fw_get_vendor(struct cam_device *cam_dev)
114{

--- 53 unchanged lines hidden (view full) ---

168 if (lseek(fd, 0, SEEK_SET) == -1) {
169 warn("Unable to lseek");
170 goto bailout;
171 }
172 if ((strncmp(buf, "SEAGATE,SEAGATE ", 16) == 0) ||
173 (img_size % 512 == 80))
174 skip_bytes = 80;
175 break;
136
137/*
138 * Find entry in vendors list that belongs to
139 * the vendor of given cam device.
140 */
141static const struct fw_vendor *
142fw_get_vendor(struct cam_device *cam_dev)
143{

--- 53 unchanged lines hidden (view full) ---

197 if (lseek(fd, 0, SEEK_SET) == -1) {
198 warn("Unable to lseek");
199 goto bailout;
200 }
201 if ((strncmp(buf, "SEAGATE,SEAGATE ", 16) == 0) ||
202 (img_size % 512 == 80))
203 skip_bytes = 80;
204 break;
205 case VENDOR_QUALSTAR:
206 skip_bytes = img_size % 1030;
207 break;
176 default:
177 break;
178 }
179 if (skip_bytes != 0) {
180 fprintf(stdout, "Skipping %d byte header.\n", skip_bytes);
181 if (lseek(fd, skip_bytes, SEEK_SET) == -1) {
182 warn("Could not lseek");
183 goto bailout;

--- 18 unchanged lines hidden (view full) ---

202/*
203 * Download firmware stored in buf to cam_dev. If simulation mode
204 * is enabled, only show what packet sizes would be sent to the
205 * device but do not sent any actual packets
206 */
207static int
208fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp,
209 char *buf, int img_size, int sim_mode, int verbose, int retry_count,
208 default:
209 break;
210 }
211 if (skip_bytes != 0) {
212 fprintf(stdout, "Skipping %d byte header.\n", skip_bytes);
213 if (lseek(fd, skip_bytes, SEEK_SET) == -1) {
214 warn("Could not lseek");
215 goto bailout;

--- 18 unchanged lines hidden (view full) ---

234/*
235 * Download firmware stored in buf to cam_dev. If simulation mode
236 * is enabled, only show what packet sizes would be sent to the
237 * device but do not sent any actual packets
238 */
239static int
240fw_download_img(struct cam_device *cam_dev, const struct fw_vendor *vp,
241 char *buf, int img_size, int sim_mode, int verbose, int retry_count,
210 int timeout)
242 int timeout, const char *imgname, const char *type)
211{
212 struct scsi_write_buffer cdb;
243{
244 struct scsi_write_buffer cdb;
245 progress_t progress;
246 int size;
213 union ccb *ccb;
214 int pkt_count = 0;
247 union ccb *ccb;
248 int pkt_count = 0;
249 int max_pkt_size;
215 u_int32_t pkt_size = 0;
216 char *pkt_ptr = buf;
217 u_int32_t offset;
218 int last_pkt = 0;
250 u_int32_t pkt_size = 0;
251 char *pkt_ptr = buf;
252 u_int32_t offset;
253 int last_pkt = 0;
254 int16_t *ptr;
219
220 if ((ccb = cam_getccb(cam_dev)) == NULL) {
221 warnx("Could not allocate CCB");
222 return (1);
223 }
255
256 if ((ccb = cam_getccb(cam_dev)) == NULL) {
257 warnx("Could not allocate CCB");
258 return (1);
259 }
224 scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG,
225 SSD_FULL_SIZE, 5000);
260 if (strcmp(type, "scsi") == 0) {
261 scsi_test_unit_ready(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG,
262 SSD_FULL_SIZE, 5000);
263 } else if (strcmp(type, "ata") == 0) {
264 /* cam_getccb cleans up the header, caller has to zero the payload */
265 bzero(&(&ccb->ccb_h)[1],
266 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
267
268 ptr = (uint16_t *)malloc(sizeof(struct ata_params));
269
270 if (ptr == NULL) {
271 cam_freeccb(ccb);
272 warnx("can't malloc memory for identify\n");
273 return(1);
274 }
275 bzero(ptr, sizeof(struct ata_params));
276 cam_fill_ataio(&ccb->ataio,
277 1,
278 NULL,
279 /*flags*/CAM_DIR_IN,
280 MSG_SIMPLE_Q_TAG,
281 /*data_ptr*/(uint8_t *)ptr,
282 /*dxfer_len*/sizeof(struct ata_params),
283 timeout ? timeout : 30 * 1000);
284 ata_28bit_cmd(&ccb->ataio, ATA_ATA_IDENTIFY, 0, 0, 0);
285 } else {
286 warnx("weird disk type '%s'", type);
287 return 1;
288 }
226 /* Disable freezing the device queue. */
227 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
228 if (cam_send_ccb(cam_dev, ccb) < 0) {
289 /* Disable freezing the device queue. */
290 ccb->ccb_h.flags |= CAM_DEV_QFRZDIS;
291 if (cam_send_ccb(cam_dev, ccb) < 0) {
229 warnx("Error sending test unit ready");
292 warnx("Error sending identify/test unit ready");
230 if (verbose)
231 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
232 CAM_EPF_ALL, stderr);
233 cam_freeccb(ccb);
234 return(1);
235 }
236 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
237 warnx("Device is not ready");
238 if (verbose)
239 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
240 CAM_EPF_ALL, stderr);
241 cam_freeccb(ccb);
242 return (1);
243 }
293 if (verbose)
294 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
295 CAM_EPF_ALL, stderr);
296 cam_freeccb(ccb);
297 return(1);
298 }
299 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
300 warnx("Device is not ready");
301 if (verbose)
302 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
303 CAM_EPF_ALL, stderr);
304 cam_freeccb(ccb);
305 return (1);
306 }
244 pkt_size = vp->max_pkt_size;
245 if (verbose || sim_mode) {
246 fprintf(stdout,
247 "--------------------------------------------------\n");
248 fprintf(stdout,
249 "PktNo. PktSize BytesRemaining LastPkt\n");
250 fprintf(stdout,
251 "--------------------------------------------------\n");
307 max_pkt_size = vp->max_pkt_size;
308 if (vp->max_pkt_size == 0 && strcmp(type, "ata") == 0) {
309 max_pkt_size = UNKNOWN_MAX_PKT_SIZE;
252 }
310 }
311 pkt_size = vp->max_pkt_size;
312 progress_init(&progress, imgname, size = img_size);
253 /* Download single fw packets. */
254 do {
313 /* Download single fw packets. */
314 do {
255 if (img_size <= vp->max_pkt_size) {
315 if (img_size <= max_pkt_size) {
256 last_pkt = 1;
257 pkt_size = img_size;
258 }
316 last_pkt = 1;
317 pkt_size = img_size;
318 }
259 if (verbose || sim_mode)
260 fprintf(stdout, "%3u %5u (0x%05X) %7u (0x%06X) "
261 "%d\n", pkt_count, pkt_size, pkt_size,
262 img_size - pkt_size, img_size - pkt_size,
263 last_pkt);
319 progress_update(&progress, size - img_size);
320 progress_draw(&progress);
264 bzero(&cdb, sizeof(cdb));
321 bzero(&cdb, sizeof(cdb));
265 cdb.opcode = WRITE_BUFFER;
266 cdb.control = 0;
267 /* Parameter list length. */
268 scsi_ulto3b(pkt_size, &cdb.length[0]);
269 offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0;
270 scsi_ulto3b(offset, &cdb.offset[0]);
271 cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2;
272 cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0;
273 /* Zero out payload of ccb union after ccb header. */
274 bzero((u_char *)ccb + sizeof(struct ccb_hdr),
275 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
276 /* Copy previously constructed cdb into ccb_scsiio struct. */
277 bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0],
278 sizeof(struct scsi_write_buffer));
279 /* Fill rest of ccb_scsiio struct. */
322 if (strcmp(type, "scsi") == 0) {
323 cdb.opcode = WRITE_BUFFER;
324 cdb.control = 0;
325 /* Parameter list length. */
326 scsi_ulto3b(pkt_size, &cdb.length[0]);
327 offset = vp->inc_cdb_offset ? (pkt_ptr - buf) : 0;
328 scsi_ulto3b(offset, &cdb.offset[0]);
329 cdb.byte2 = last_pkt ? vp->cdb_byte2_last : vp->cdb_byte2;
330 cdb.buffer_id = vp->inc_cdb_buffer_id ? pkt_count : 0;
331 /* Zero out payload of ccb union after ccb header. */
332 bzero((u_char *)ccb + sizeof(struct ccb_hdr),
333 sizeof(struct ccb_scsiio) - sizeof(struct ccb_hdr));
334 /* Copy previously constructed cdb into ccb_scsiio struct. */
335 bcopy(&cdb, &ccb->csio.cdb_io.cdb_bytes[0],
336 sizeof(struct scsi_write_buffer));
337 /* Fill rest of ccb_scsiio struct. */
338 if (!sim_mode) {
339 cam_fill_csio(&ccb->csio, /* ccb_scsiio */
340 retry_count, /* retries */
341 NULL, /* cbfcnp */
342 CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags */
343 CAM_TAG_ACTION_NONE, /* tag_action */
344 (u_char *)pkt_ptr, /* data_ptr */
345 pkt_size, /* dxfer_len */
346 SSD_FULL_SIZE, /* sense_len */
347 sizeof(struct scsi_write_buffer), /* cdb_len */
348 timeout ? timeout : CMD_TIMEOUT); /* timeout */
349 }
350 } else if (strcmp(type, "ata") == 0) {
351 bzero(&(&ccb->ccb_h)[1],
352 sizeof(struct ccb_ataio) - sizeof(struct ccb_hdr));
353 if (!sim_mode) {
354 uint32_t off;
355
356 cam_fill_ataio(&ccb->ataio,
357 (last_pkt) ? 256 : retry_count,
358 NULL,
359 /*flags*/CAM_DIR_OUT | CAM_DEV_QFRZDIS,
360 CAM_TAG_ACTION_NONE,
361 /*data_ptr*/(uint8_t *)pkt_ptr,
362 /*dxfer_len*/pkt_size,
363 timeout ? timeout : 30 * 1000);
364 off = (uint32_t)(pkt_ptr - buf);
365 ata_28bit_cmd(&ccb->ataio, ATA_DOWNLOAD_MICROCODE,
366 USE_OFFSETS_FEATURE,
367 ATA_MAKE_LBA(off, pkt_size),
368 ATA_MAKE_SECTORS(pkt_size));
369 }
370 }
280 if (!sim_mode) {
371 if (!sim_mode) {
281 cam_fill_csio(&ccb->csio, /* ccb_scsiio */
282 retry_count, /* retries */
283 NULL, /* cbfcnp */
284 CAM_DIR_OUT | CAM_DEV_QFRZDIS, /* flags */
285 CAM_TAG_ACTION_NONE, /* tag_action */
286 (u_char *)pkt_ptr, /* data_ptr */
287 pkt_size, /* dxfer_len */
288 SSD_FULL_SIZE, /* sense_len */
289 sizeof(struct scsi_write_buffer), /* cdb_len */
290 timeout ? timeout : CMD_TIMEOUT); /* timeout */
291 /* Execute the command. */
292 if (cam_send_ccb(cam_dev, ccb) < 0) {
293 warnx("Error writing image to device");
294 if (verbose)
295 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
372 /* Execute the command. */
373 if (cam_send_ccb(cam_dev, ccb) < 0) {
374 warnx("Error writing image to device");
375 if (verbose)
376 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
296 CAM_EPF_ALL, stderr);
377 CAM_EPF_ALL, stderr);
297 goto bailout;
298 }
378 goto bailout;
379 }
380 if (ccb->ataio.res.status != 0 /*&& !last_pkt*/) {
381 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
382 CAM_EPF_ALL, stderr);
383 }
299 }
300 /* Prepare next round. */
301 pkt_count++;
302 pkt_ptr += pkt_size;
303 img_size -= pkt_size;
304 } while(!last_pkt);
384 }
385 /* Prepare next round. */
386 pkt_count++;
387 pkt_ptr += pkt_size;
388 img_size -= pkt_size;
389 } while(!last_pkt);
305 if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
306 if (verbose)
307 cam_error_print(cam_dev, ccb, CAM_ESF_ALL,
308 CAM_EPF_ALL, stderr);
309 goto bailout;
310 }
390 progress_complete(&progress, size - img_size);
311 cam_freeccb(ccb);
312 return (0);
313bailout:
391 cam_freeccb(ccb);
392 return (0);
393bailout:
394 progress_complete(&progress, size - img_size);
314 cam_freeccb(ccb);
315 return (1);
316}
317
318int
319fwdownload(struct cam_device *device, int argc, char **argv,
395 cam_freeccb(ccb);
396 return (1);
397}
398
399int
400fwdownload(struct cam_device *device, int argc, char **argv,
320 char *combinedopt, int verbose, int retry_count, int timeout)
401 char *combinedopt, int verbose, int retry_count, int timeout,
402 const char *type)
321{
322 const struct fw_vendor *vp;
323 char *fw_img_path = NULL;
324 char *buf;
325 int img_size;
326 int c;
327 int sim_mode = 0;
328 int confirmed = 0;

--- 11 unchanged lines hidden (view full) ---

340 confirmed = 1;
341 break;
342 default:
343 break;
344 }
345 }
346
347 if (fw_img_path == NULL)
403{
404 const struct fw_vendor *vp;
405 char *fw_img_path = NULL;
406 char *buf;
407 int img_size;
408 int c;
409 int sim_mode = 0;
410 int confirmed = 0;

--- 11 unchanged lines hidden (view full) ---

422 confirmed = 1;
423 break;
424 default:
425 break;
426 }
427 }
428
429 if (fw_img_path == NULL)
348 errx(1,
349 "you must specify a firmware image file using -f option");
430 errx(1, "you must specify a firmware image file using -f option");
350
351 vp = fw_get_vendor(device);
431
432 vp = fw_get_vendor(device);
352 if (vp == NULL || vp->type == VENDOR_UNKNOWN)
353 errx(1, "Unsupported device");
433 if (vp == NULL)
434 errx(1, "NULL vendor");
435 if (vp->type == VENDOR_UNKNOWN)
436 warnx("Unsupported device - flashing through an HBA?");
354
355 buf = fw_read_img(fw_img_path, vp, &img_size);
356 if (buf == NULL)
357 goto fail;
358
359 if (!confirmed) {
360 fprintf(stdout, "You are about to download firmware image (%s)"
361 " into the following device:\n",
362 fw_img_path);
437
438 buf = fw_read_img(fw_img_path, vp, &img_size);
439 if (buf == NULL)
440 goto fail;
441
442 if (!confirmed) {
443 fprintf(stdout, "You are about to download firmware image (%s)"
444 " into the following device:\n",
445 fw_img_path);
363 if (scsidoinquiry(device, argc, argv, combinedopt, 0,
364 5000) != 0) {
365 warnx("Error sending inquiry");
366 goto fail;
367 }
368 fprintf(stdout, "\nIt may damage your drive. ");
369 if (!get_confirmation())
370 goto fail;
371 }
372 if (sim_mode)
373 fprintf(stdout, "Running in simulation mode\n");
374
375 if (fw_download_img(device, vp, buf, img_size, sim_mode, verbose,
446 fprintf(stdout, "\nIt may damage your drive. ");
447 if (!get_confirmation())
448 goto fail;
449 }
450 if (sim_mode)
451 fprintf(stdout, "Running in simulation mode\n");
452
453 if (fw_download_img(device, vp, buf, img_size, sim_mode, verbose,
376 retry_count, timeout) != 0) {
454 retry_count, timeout, fw_img_path, type) != 0) {
377 fprintf(stderr, "Firmware download failed\n");
378 goto fail;
455 fprintf(stderr, "Firmware download failed\n");
456 goto fail;
379 } else
457 }
458 else
380 fprintf(stdout, "Firmware download successful\n");
381
382 free(buf);
383 return (0);
384fail:
385 if (buf != NULL)
386 free(buf);
387 return (1);
388}
389
459 fprintf(stdout, "Firmware download successful\n");
460
461 free(buf);
462 return (0);
463fail:
464 if (buf != NULL)
465 free(buf);
466 return (1);
467}
468