Emulex Logo
OneCore™ Storage SDK Release 11.2
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
elxu_dwnld.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011-2015, Emulex
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <stdlib.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <sys/stat.h>
40 #include <ctype.h>
41 #include <unistd.h>
42 #include <memory.h>
43 #include <errno.h>
44 #include <sys/times.h>
45 #include <sys/ioctl.h>
46 #include <time.h>
47 
48 #include <elxu_sli4.h>
49 #include <elxu_device.h>
50 #include <elxu_sky.h>
51 #include <elxu_ufi.h>
52 #include <elxu_dwnld.h>
53 #include <elxu_common.h>
54 #include <elxu_mgmt.h>
55 
56 #include <ocs_ioctl.h>
57 
58 #define FW_UPDATE_RESTRICTED -14
59 #define UNSUPPORTED_FW_IMAGE -13
60 
61 static uint16_t get_op_type(uint8_t entry_type);
62 static off_t find_ufi_dir(int fd);
63 
64 /**
65  * @brief Returns the file type.
66  *
67  * This function returns the type of the file - Skyhawk UFI or Lancer object file.
68  *
69  * @param buf_p pointer to the memory holding an initial file data
70  * @param len the data length
71  */
72 
73 static fFormat_t retrieve_file_format (uint8_t *buf_p, int len)
74 {
75  fFormat_t result = UNKNOWN;
76  uint32_t dw2;
77 
78  /*
79  * Skyhawk UFI files always starts with 'S' character .
80  * It is the first letter of a "ServerEngines" string.
81  */
82  if (buf_p [0] == 'S' ) {
83  ufi_file_header_t *file_hdr;
84 
85  file_hdr = (ufi_file_header_t *)buf_p;
86 
87  /*
88  * In the Skyhawk format the first byte of the build_version field
89  * gives us the device family. 4=Skyhawk
90  */
91  if (file_hdr->build_version[0] == '4') {
92  result = SKYHAWK_UFI;
93  }
94  } else {
95  dw2 = *(uint32_t *) &buf_p[4];
96 
97  /*
98  * Verify if the file is an Lancer Object file.
99  * 0xFEAA is a magic number, 0001 (normal) and 0002 (compressed) is a file types
100  * 0003 seems to be a new valure for Lancer G6 files, 0005 is for Prism.
101  */
102  if ((dw2 == 0xFEAA0001) || (SWAP_4BYTES(dw2) == 0xFEAA0001) ||
103  (dw2 == 0xFEAA0002) || (SWAP_4BYTES(dw2) == 0xFEAA0002) ||
104  (dw2 == 0xFEAA0003) || (SWAP_4BYTES(dw2) == 0xFEAA0003) )
105  {
106  result = LANCER;
107  } else if ((dw2 == 0xFEAA0005) || (SWAP_4BYTES(dw2) == 0xFEAA0005)) {
108  result = PRISM;
109  }
110  }
111 
112  return result;
113 }
114 
115 
116 /**
117  * @brief Initializes files descriptor structure.
118  *
119  * Initializes the file descriptor structure.
120  *
121  * @param file_name_p filename information
122  * @param fdsc_p a file descriptor pointer
123  */
124 
125 static int file_handler_init (const char *filename_p, dwnld_file_desc_t *fdesc_p)
126 {
127  uint8_t *buf_p;
128  int rd;
129  const char *str_p;
130  off_t ufi_dir_offset;
131  int rc;
132 
133  /*
134  * Get a file statistic information (file length and ...)
135  */
136  rc = stat(filename_p, &(fdesc_p->st));
137  if (rc < 0)
138  {
139  if (errno == ENOENT) {
140  printf("File %s not found\n", filename_p);
141  } else {
142  printf("File %s stat returns %s\n", filename_p, strerror(errno));
143  }
144  return -1;
145  }
146 
147  str_p = strrchr (filename_p, '/');
148 
149  if (str_p == NULL)
150  {
151  str_p = filename_p;
152  }
153  else
154  {
155  str_p++;
156  }
157 
158  if(strlen(str_p) < 127 ) {
159  strncpy (fdesc_p->file_name, str_p, strlen(str_p));
160  }else {
161  printf ("file name more than 128 chars\n");
162  return -1;
163  }
164 
165  /*
166  * Open the file ..
167  */
168  if ((fdesc_p->fd = open(filename_p, O_RDONLY)) < 0)
169  {
170  printf ("open file failure, (%s)\n", strerror(errno));
171  return -1;
172  }
173 
174  /*
175  * Allocate a space the file header information.
176  * This includes both the UFI File Header and the Image Header for a UFI file
177  *
178  * UFI header is bigger than Lancer file object header.
179  * Allocate the space to fit UFI header.
180  *
181  */
182  if ((buf_p = zmalloc(UFI_FILE_HEADER_LENGTH)) == NULL)
183  {
184  close(fdesc_p->fd);
185  printf("Malloc failure - (%s)\n", strerror(errno));
186  return MALLOC_FAILED;
187  }
188 
189  /*
190  * Copy data into the memory
191  */
192  if ((rd = read(fdesc_p->fd, buf_p, UFI_FILE_HEADER_LENGTH)) != UFI_FILE_HEADER_LENGTH)
193  {
194  printf("Read failure %d, (%s)\n", rd, strerror(errno));
195  zfree(buf_p);
196  close(fdesc_p->fd);
197  return -1;
198  }
199 
200  /*
201  * Get the file type and update file descriptor fields.
202  */
204  {
205 
206  case SKYHAWK_UFI:
207  fdesc_p->file_type = FILE_TYPE_UFI;
208  fdesc_p->hba_file_type = HBA_FILE_SKYHAWK;
209  fdesc_p->ufi_flash_hdr = zmalloc(sizeof(flash_directory_t));
210  ufi_dir_offset = find_ufi_dir(fdesc_p->fd);
211  if (ufi_dir_offset < 0) {
212  printf("Unable to find UFI directory in UFI file.\n");
213  zfree(buf_p);
214  close(fdesc_p->fd);
215  return -1;
216  }
217  if(lseek(fdesc_p->fd, ufi_dir_offset, SEEK_SET)) {
218  /* copy in our UFI flash directory header */
219  read(fdesc_p->fd, fdesc_p->ufi_flash_hdr, sizeof(flash_directory_t));
220  }
221 
222  /* First 128 bytes are the UFI header */
223  memcpy((uint8_t *)&(fdesc_p->ufi_hdr), buf_p, sizeof(ufi_file_header_t));
224  /* Next 48 bytes are the Image Header */
225  memcpy((uint8_t *)&(fdesc_p->img_hdr), (buf_p + sizeof(ufi_file_header_t)), sizeof(ufi_image_header_t));
226 
227  break;
228 
229  case LANCER:
230  fdesc_p->hba_file_type = HBA_FILE_LANCER;
231  break;
232  case PRISM:
233  fdesc_p->hba_file_type = HBA_FILE_PRISM;
234  break;
235 
236  case UNKNOWN:
237  printf ("Unsupported file type.\n");
238  zfree(buf_p);
239  close(fdesc_p->fd);
240  return -1;
241  }
242 
243  /*
244  * Reset the file reader location.
245  */
246  lseek(fdesc_p->fd, 0, SEEK_SET);
247  zfree(buf_p);
248  return 0;
249 } /* end of download_ufi_file_int */
250 
251 
252 
253 /**
254  * @brief Displays content of UFI file header structure.
255  *
256  * The function parses and displays the content of the UFI file header structure.
257  *
258  * @param ufi_hdr_p UFI header structure pointer.
259  */
260 
261 static void display_ufi_header(ufi_file_header_t *ufi_hdr_p)
262 {
263  int i;
264 
265  printf("\nUFI File Header:\n");
266  printf("Signature:\n");
267  for (i = 0; i < 52; i++)
268  {
269  if (isprint(ufi_hdr_p->signature[i])) {
270  printf("%c", ufi_hdr_p->signature[i]);
271  }
272  }
273 
274  printf("\nUFI Version: %08x\n", ufi_hdr_p->ufi_version);
275  printf("FileLen: %d (%08X)\n", ufi_hdr_p->file_len, ufi_hdr_p->file_len);
276  printf("Checksum : %08X\n", ufi_hdr_p->checksum);
277  printf("Antidote: %08X\n", ufi_hdr_p->antidote);
278  printf("Number of Images: %d\n", ufi_hdr_p->numOfImgs);
279  printf("Build: %s\n", trimmed_string(ufi_hdr_p->build_version));
280  printf("Target platform: ");
281  switch(ufi_hdr_p->build_version[0]) {
282  case '4':
283  printf("Skyhawk\n");
284  break;
285  default:
286  printf("Unknown\n");
287  }
288  printf("ASIC Support: 0x%x", ufi_hdr_p->asic_support);
289  if (ufi_hdr_p->build_version[0] == '4') {
290  if (ufi_hdr_p->asic_support == 0x10) {
291  printf(" (Skyhawk B0 only)\n");
292  } else if (ufi_hdr_p->asic_support == 0x11) {
293  printf(" (Skyhawk B0 or B1 only)\n");
294  }
295  } else {
296  printf("\n");
297  }
298  printf("End of UFI File Header dump\n");
299 }
300 
301 /**
302  * @brief Displays content of UFI flash directory header.
303  *
304  * This function is in part used for debugging and determining what sections exist
305  * in a given UFI file
306  *
307  * @param flash_dir UFI flash directory structure pointer.
308  */
310 {
311  int i;
312  flash_directory_t *flash_dir = fdesc->ufi_flash_hdr;
314  uint32_t crc;
315  off_t offset;
316 
317  printf("\nFlash Directory Header:\n");
318  printf("Flash Directory Format: %d\n", flash_dir->formatRevNumber);
319  printf("Number of Directory Entries: %d\n", flash_dir->numImages);
320 
321  printf("Flash Directory Entries:\n");
322  for (i=0; i<flash_dir->numImages; i++) {
323  entry = &(flash_dir->entries[i]);
324 
325  printf(" Version: %s\n", trimmed_string(entry->version));
326  printf(" Entry Type: 0x%02x (%s)\n", entry->entryType, decode_entry_type(entry->entryType));
327  if (entry->opType == 0xffff) {
328  printf(" Op Type: 0x%04x (based on Entry Type)\n", get_op_type(entry->entryType));
329  } else {
330  printf(" Op Type: 0x%04x\n", entry->opType);
331  }
332  printf(" Offset: 0x%08x\n", entry->offset);
333  printf(" Image Size: 0x%08x\n", entry->imageSize);
334  printf(" Max Image Size: 0x%08x\n", entry->maxSize);
335  printf(" Checksum: 0x%08x\n", entry->checkSum);
336 
337  /* Get CRC from the end of the actual component */
338  offset = (long)(entry->offset + entry->maxSize + UFI_FILE_HEADER_LENGTH - 4);
339  if (lseek(fdesc->fd, offset , SEEK_SET) != offset) {
340  fprintf(stderr, "couldn't seek to %ld\n", offset);
341  return;
342  }
343 
344  if (read(fdesc->fd, &crc, 4) != 4) {
345  fprintf(stderr, "Didn't get %d bytes on read\n", 4);
346  return;
347  }
348  printf(" CRC: 0x%08x\n", crc);
349  }
350 
351  printf("\nEnd of Flash Directory Listing dump\n");
352 }
353 
354 /**
355  * @brief Displays content of UFI image header structure.
356  *
357  * The function displays the content of the UFI image header structure.
358  *
359  * @param ufi_hdr_p UFI image header structure pointer.
360  */
361 
363 {
364 
365  printf("\nFirmware Image Header:\n");
366  printf("Image ID: %08X\n", img_hdr_p->imageId);
367  printf("Image Offset: %08X\n", img_hdr_p->imageOffset);
368  printf("Image Length: %08X\n", img_hdr_p->imageLength);
369  printf("Image Checksum: %08X\n", img_hdr_p->imageChecksum);
370  printf("Image Version: %s\n", trimmed_string(img_hdr_p->imageVer));
371  printf("End of Firmware Image Header dump\n");
372 
373 }
374 
375 /**
376  * @brief Skyhawk firmware download.
377  *
378  * Skyhawk UFI file is read into memory and it is forwarded to the HBA in segments.
379  *
380  * @param device_p A pointer to HBA structure descriptor.
381  * @param fdsc_p A pointer to a file descriptor structure.
382  */
383 
385 {
386  flash_directory_t *ufi_dir;
387  int entry_index;
388  int largest_entry;
389  uint8_t *buffer;
390  int rval;
391  long lval;
392  int asic_support_ok;
393 
394  ufi_dir = fdsc_p->ufi_flash_hdr;
395 
396  /*
397  * Check the ASIC_Support field in the UFI header and see if this firmware
398  * is supported on the target ASIC.
399  */
400 
401  asic_support_ok = 0;
402  switch(fdsc_p->ufi_hdr.asic_support) {
403  case 0x10:
404  /* B0 Firmware, supported only on B0 chips */
405  if (device_p->asic_id == 0x0410) {
406  asic_support_ok = 1;
407  }
408  break;
409  case 0x11:
410  /* B1 Firmware, supported on B0 and B1 chips */
411  if ((device_p->asic_id == 0x0410) ||
412  (device_p->asic_id == 0x0411)) {
413  asic_support_ok = 1;
414  }
415  break;
416  default:
417  /* Undefined asic_support value */
418  break;
419  }
420 
421 
422  if (asic_support_ok == 0) {
423  printf("Provided UFI is not supported on this device.\n");
424  printf("UFI version is 0x%02x, device version is 0x%04x\n",
425  fdsc_p->ufi_hdr.asic_support,
426  device_p->asic_id);
427  close(fdsc_p->fd);
428  return -1;
429  }
430 
431  display_ufi_header(&fdsc_p->ufi_hdr);
432  display_ufi_image_hdr(&fdsc_p->img_hdr);
434 
435  /*
436  * Allocate a buffer big enough to hold the largest FW section.
437  */
438  largest_entry = 0;
439  for (entry_index=0; entry_index < ufi_dir->numImages; entry_index++) {
440  if (ufi_dir->entries[entry_index].maxSize > largest_entry) {
441  largest_entry = ufi_dir->entries[entry_index].maxSize;
442  }
443  }
444  buffer = malloc(largest_entry);
445  if (buffer == NULL) {
446  printf("Unable to allocate memory to hold FW image\n");
447  return -1;
448  }
449 
450  for (entry_index=0; entry_index < ufi_dir->numImages; entry_index++) {
452  uint32_t op_type;
453  uint32_t entry_type;
454  uint32_t offset;
455  uint32_t file_crc;
456  uint32_t chip_crc;
457  off_t seek_offset;
458 
459  entry = &(ufi_dir->entries[entry_index]);
460  op_type = entry->opType;
461  entry_type = entry->entryType;
462  if (op_type == 0xffff) {
463  op_type = get_op_type(entry_type);
464  }
465  offset = entry->offset;
466 
467  if (op_type == 0xffff) {
468  printf("Invalid op_type for section %d\n", entry_index);
469  free(buffer);
470  return -1;
471  }
472 
473  /* Read the CRC of the current segment on the device */
474  rval = mbox_read_flashrom(device_p, MGMT_FLASHROM_OPCODE_IMAGE_CRC, op_type, offset, buffer, 4);
475  /* If reading the CRC failed then we'll just assume the CRCs are different */
476  if (rval == 0) {
477  chip_crc = (buffer[3] << 24) | (buffer[2] << 16) | (buffer[1] << 8) | buffer[0];
478 
479  /* Read the CRC from the firmware file */
480  seek_offset = entry->offset + entry->maxSize + UFI_FILE_HEADER_LENGTH - 4;
481  if (lseek(fdsc_p->fd, seek_offset , SEEK_SET) != seek_offset) {
482  fprintf(stderr, "couldn't seek to %ld\n", seek_offset);
483  }
484  if (read(fdsc_p->fd, &file_crc, 4) != 4) {
485  fprintf(stderr, "Didn't get %d bytes on read\n", 4);
486  }
487 
488  /*
489  * Compare the CRC from the running FW with the CRC in the file
490  * If they match we can skip this section.
491  */
492 
493  if (chip_crc == file_crc) {
494  printf("%08x: [%s] Unchanged, skipping\n", entry->offset, trimmed_string(entry->version));
495  continue;
496  }
497  }
498 
499  printf("%08x: [%s] (%d bytes)\n", entry->offset, trimmed_string(entry->version), entry->maxSize);
500 
501  lval = lseek(fdsc_p->fd, entry->offset+UFI_FILE_HEADER_LENGTH, SEEK_SET);
502  if (lval != entry->offset+UFI_FILE_HEADER_LENGTH) {
503  printf("Seek failed to offset 0x%x\n", entry->offset);
504  free(buffer);
505  return -1;
506  }
507 
508  lval = read(fdsc_p->fd, buffer, entry->maxSize);
509  if (lval != entry->maxSize) {
510  printf("Read failed in segment %d\n", entry_index);
511  printf("Expected %d bytes, got %ld\n", entry->maxSize, lval);
512  free(buffer);
513  return -1;
514  }
515 
516  rval = ufi_image_download(device_p, op_type, buffer, entry->maxSize);
517  if (rval != 0) {
518  /* This section of code is temporary (as of March 2014) for the transition between
519  old and new Skyhawk firmware */
520  if (entry->opType == 0xffff) {
521  if ((entry_type == 0x30) ||
522  (entry_type == 0xc0) ||
523  (entry_type == 0xd0) ||
524  (entry_type == 0xd1) ||
525  (entry_type == 0xd2)) {
526  if ((rval == -2) || (rval == -3)) {
527  /* It's OK to ignore this error */
528  continue;
529  }
530  }
531  }
532 
533  /* At this point we have an error, and it's not one of the cases we're supposed to ignore */
534  if ((rval == -2) || (rval == -3)) {
535  /*
536  * These two errors indicate a case where we're moving from old style
537  * firmware to new style. This requires a reboot and a second download of
538  * the same firmware.
539  */
540  printf("This special firmware release requires the firmware download process\n");
541  printf("to be performed twice. You must reboot the system and download the same\n");
542  printf("firmware file again to complete the download process.\n");
543  free(buffer);
544  return -1;
545  } else {
546  /*
547  * Some other unexpected error has occurred.
548  */
549  printf("Firmware download failed, status is 0x%02x\n", -rval);
550  free(buffer);
551  return -1;
552  }
553 
554  }
555 
556  }
557 
558  printf("Firmware download successful.\n");
559  printf("Reboot the system to activate the new firmware.\n");
560 
561  free(buffer);
562  return 0;
563 
564 }
565 
566 
567 /**
568  * @brief Lancer file object.
569  *
570  * Downloads the Lancer file object into specified HBA object directory (object).
571  *
572  * @param device_p A pointer to HBA structure descriptor.
573  * @param object_p An lancer object type
574  * @param fdsc_p A pointer to a file descriptor structure.
575  */
576 
577 static int download_lancer_object_file (elxu_device_t *device_p, const char *object_p, dwnld_file_desc_t *fdsc_p)
578 {
579  struct stat stat_buf;
580  unsigned char *buf;
581  off_t filesize;
582  int rval;
583  char change_status_text[20];
584  int change_status;
585 
586  if (fstat(fdsc_p->fd, &stat_buf) == -1) {
587  perror("fstat");
588  return -1;
589  }
590 
591  filesize = stat_buf.st_size;
592 
593  buf = malloc(filesize);
594  if (buf == NULL) {
595  perror("malloc");
596  return -1;
597  }
598 
599  if (read(fdsc_p->fd, buf, filesize) != filesize) {
600  fprintf(stderr, "Didn't get %ld bytes on read\n", filesize);
601  free(buf);
602  return -1;
603  }
604 
605  rval = elxu_device_exec(device_p, "/ocs/firmware_write", buf, filesize, change_status_text, 20);
606  if (rval == 0) {
607  printf("Firmware download successful.\n");
608  change_status = strtoul(change_status_text, NULL, 0);
609  switch (change_status) {
610  case 0x00:
611  printf("No reset needed, new firmware is active.\n");
612  break;
613  case 0x01:
614  printf("A physical device reset (host reboot) is needed to activate the new firmware\n");
615  break;
616  case 0x02:
617  case 0x03:
618  printf("Use the firmware-reset option to activate the new firmware.\n");
619  break;
620  case 0x04:
621  printf("Use port-migration or firmware-reset option to activate new firmware.\n");
622  printf("Note: With port-migration option, Only particular port will run with new FW\n");
623  break;
624  default:
625  printf("Unexected value for change_status: %d\n", change_status);
626  break;
627  }
628  } else if (rval == FW_UPDATE_RESTRICTED) {
629  printf("This firmware version is not supported on this HBA model.\n");
630  } else if (rval == UNSUPPORTED_FW_IMAGE) {
631  printf("Download failed. Firmware does not meet minimum version requirement.\n");
632  } else {
633  perror("ioctl");
634  }
635 
636  free(buf);
637  return rval;
638 
639 }
640 
641 
642 /**
643  * @brief Lancer firmware download.
644  *
645  * Donwloads the grp file into HBA.
646  *
647  * @param device_p A pointer to HBA structure descriptor.
648  * @param fdsc_p A pointer to a file descriptor structure.
649  */
650 
652 {
653  int retval = -1;
654 
655  /*
656  * Validate the file type using the file extention.
657  */
658  if (strstr (fdsc_p->file_name, ".grp") != NULL)
659  {
660  /*
661  * When .grp file, use only the object name - clear file name
662  */
663  fdsc_p->file_name[0] = '\0';
664  retval = download_lancer_object_file (device_p, "/prg/", fdsc_p);
665  }
666  else
667  {
668  printf ("The file %s has to be a .grp file type \n", fdsc_p->file_name);
669  }
670  return retval;
671 }
672 
673 
674 /**
675  * @brief Firmware download.
676  *
677  * Based on the file type, download the firmware to an appropriate HBA.
678  *
679  * @param device_p A pointer to HBA structure descriptor.
680  * @param fdsc_p A pointer to a file descriptor structure.
681  *
682  * @return Returns 0 on success, non-zero on failure.
683  */
684 
685 static int download_handler(elxu_device_t *device_p, dwnld_file_desc_t *fdsc_p)
686 {
687  int retval;
688 
689  switch (fdsc_p->hba_file_type) {
690  case HBA_FILE_SKYHAWK:
691  if (is_skyhawk(device_p)) {
692  printf("Download starting\n");
693  retval = download_skyhawk_image (device_p, fdsc_p);
694  } else {
695  printf("Firmware is Skyhawk UFI but device is not Skyhawk\n");
696  retval = -1;
697  }
698  break;
699  case HBA_FILE_LANCER:
700  case HBA_FILE_PRISM:
701  if (is_lancer(device_p) || is_prism(device_p)) {
702  printf("Download starting\n");
703  retval = download_lancer_image (device_p, fdsc_p);
704  } else {
705  printf("Firmware is Lancer FW file but device is not Lancer\n");
706  retval = -1;
707  }
708  break;
709  default:
710  printf ("Unknown HBA file type %d \n", fdsc_p->hba_file_type);
711  retval = -1;
712  }
713 
714  if (retval < 0) {
715  printf ("Download Failed\n");
716  } else
717  {
718  printf("Download Success\n");
719  if (is_calypso(device_p)) {
720  printf("NOTE: The interface just updated is a dual controller interface.\n");
721  printf(" You may need to update the firmware on the second controller\n");
722  printf(" to prevent issues on next boot.\n");
723  }
724  }
725 
726  return retval;
727 
728 }
729 
730 /**
731  * @brief flash and file data comparison functionality.
732  *
733  * Compare flash with the UFI or Bin file data.
734  *
735  * @param device_p The pointer to the HBA descriptor structure.
736  * @param memFdsc_p The pointer to the memory file descriptor structure.
737  */
738 
740 {
741  int failure_detected = 0;
742  uint8_t *file_sect_buf_p;
743  uint8_t *flash_sect_buf_p;
744  flash_directory_t *ufi_dir;
745  int entry_index;
746  int largest_entry;
747  long lval;
748 
749  if (device_p == NULL || fdsc_p == NULL)
750  {
751  printf("Null pointer \n");
752  return (-1);
753  }
754 
755  ufi_dir = fdsc_p->ufi_flash_hdr;
756 
757  /*
758  * Validate the file type: UFI or Bin
759  */
760  if (fdsc_p->file_type != FILE_TYPE_UFI)
761  {
762  printf("FW file is not a UFI file\n");
763  return -1;
764  }
765 
766  printf ("Verify firmware sections ... \n\n");
767 
768  /*
769  * Find the size of the largest UFI entry
770  */
771  largest_entry = 0;
772  for (entry_index=0; entry_index < ufi_dir->numImages; entry_index++) {
773  if (ufi_dir->entries[entry_index].maxSize > largest_entry) {
774  largest_entry = ufi_dir->entries[entry_index].maxSize;
775  }
776  }
777 
778  /*
779  * Allocate a buffer for FW sections from the file
780  */
781  if ((file_sect_buf_p = malloc(largest_entry)) == NULL)
782  {
783  printf("Malloc failure (%s)\n", strerror(errno));
784  close (fdsc_p->fd);
785  return MALLOC_FAILED;
786  }
787 
788  /*
789  * Allocate a buffer for FW sections from flash
790  */
791  if ((flash_sect_buf_p = malloc(largest_entry)) == NULL)
792  {
793  printf("Malloc failure (%s)\n", strerror(errno));
794  close (fdsc_p->fd);
795  free(file_sect_buf_p);
796  return MALLOC_FAILED;
797  }
798 
799  /* Iterate over entries in the UFI dirctory */
800  for (entry_index=0; entry_index < ufi_dir->numImages; entry_index++) {
802  uint32_t op_type;
803  uint32_t entry_type;
804 
805  printf("%d: ", entry_index);
806 
807  entry = &(ufi_dir->entries[entry_index]);
808  op_type = entry->opType;
809  entry_type = entry->entryType;
810  if (op_type == 0xffff) {
811  op_type = get_op_type(entry_type);
812  }
813 
814  if (op_type == 0xffff) {
815  printf("ERROR: Invalid op_type\n");
816  ++failure_detected;
817  continue;
818  }
819 
820  /* Read the section from the file */
821  lval = lseek(fdsc_p->fd, entry->offset+UFI_FILE_HEADER_LENGTH, SEEK_SET);
822  if (lval != entry->offset+UFI_FILE_HEADER_LENGTH) {
823  printf("ERROR: File seek failed\n");
824  ++failure_detected;
825  continue;
826  }
827 
828  lval = read(fdsc_p->fd, file_sect_buf_p, entry->maxSize);
829  if (lval != entry->maxSize) {
830  printf("ERROR: File read failed\n");
831  ++failure_detected;
832  continue;
833  }
834 
835  /* Read the section from the firmware */
836  if (ufi_image_upload(device_p, op_type, flash_sect_buf_p, entry->maxSize) != 0)
837  {
838  printf ("ERROR: Firmware read failed\n");;
839  ++failure_detected;
840  continue;
841  }
842 
843  /*
844  * Compare buffers
845  */
846  if (memcmp(flash_sect_buf_p, file_sect_buf_p, entry->maxSize) != 0)
847  {
848  printf("MISMATCH: Sections do not match\n");
849  failure_detected++;
850  continue;
851  } else {
852  printf("Match\n");
853  }
854 
855  }
856 
857  /*
858  * Mismatch detected
859  */
860  if (failure_detected)
861  {
862  printf("Firmware verification failed - %d mismatched sections \n",
863  failure_detected);
864  }
865  else
866  {
867  printf("Firmware verification was successful! \n");
868  }
869  zfree(file_sect_buf_p);
870  zfree(flash_sect_buf_p);
871  zfree(fdsc_p->ufi_flash_hdr);
872  close(fdsc_p->fd);
873  return 0;
874 }
875 
876 /**
877  * @brief Determine mailbox op_type from UFI entry_type.
878  *
879  * @par Description
880  * Each firmware section in a UFI directory has an entry type that
881  * describes what type of entry it it. Newer UFI files also have
882  * an op_type field that specify which op_type argument should be
883  * passed in the COMMON_WRITE_FLASHROM mailbox comman. Older UFI
884  * files don't have the op_type present in the directory and it must
885  * be determined from the entry_type. This function returns an
886  * op_type based on the entry_type.
887  *
888  * @param entry_type The entry type to look up.
889  *
890  * @return Returns the op_type that corresponds to the given entry type,
891  * or 0xffff if no match is found.
892  */
893 static uint16_t get_op_type(uint8_t entry_type)
894 {
895  static int table[][2] = {
896  {0x10, 0x000d},
897  {0xa0, 0x0000},
898  {0xb0, 0x0009},
899  {0x20, 0x0003},
900  {0x21, 0x0008},
901  {0x22, 0x0002},
902  {0xe0, 0x0001},
903  {0x30, 0x0016},
904  {0xc0, 0x0015},
905  {0xd0, 0x0012},
906  {0xd1, 0x0013},
907  {0xd2, 0x0017},
908  {0xd3, 0x0014},
909  {0x23, 0x0011},
910  };
911  int i;
912 
913  for (i=0; i<sizeof(table) / sizeof(table[0][0]) / 2; i++) {
914  if (table[i][0] == entry_type) {
915  return table[i][1];
916  }
917  }
918 
919  return 0xffff;
920 }
921 
922 #define PATTERN_SIZE 16
923 
924 static off_t find_ufi_dir(int fd)
925 {
926  uint8_t buffer[PATTERN_SIZE];
927  static uint8_t pattern1[PATTERN_SIZE] = {
928  '*', '*', '*', ' ', 'S', 'E', ' ', 'F',
929  'L', 'A', 'S', '\0', '\0', '\0', '\0', '\0'};
930  static uint8_t pattern2[PATTERN_SIZE] = {
931  'H', ' ', 'D', 'I', 'R', 'E', 'C', 'T',
932  'O', 'R', 'Y', ' ', '*', '*', '*', ' '};
933  off_t result;
934 
935  lseek(fd, 0, SEEK_SET);
936  result = 0;
937  while (read(fd, buffer, PATTERN_SIZE) == PATTERN_SIZE) {
938  if (memcmp(buffer, pattern1, PATTERN_SIZE) == 0) {
939  if (read(fd, buffer, PATTERN_SIZE) != PATTERN_SIZE) {
940  fprintf(stderr , "couldn't read %d bytes" , PATTERN_SIZE);
941  }
942  if (memcmp(buffer, pattern2, PATTERN_SIZE) == 0) {
943  return result;
944  } else {
945  return -1;
946  }
947  }
948  result += PATTERN_SIZE;
949  }
950 
951  return -1;
952 
953 }
954 
955 /**
956  * @brief File manipulating functionality.
957  *
958  * This functionality is called by a CLI to request a particular file
959  * manipulation operation.
960  *
961  * @param device_p The pointer to the HBA descriptor structure.
962  * @param memFdsc_p The pointer to the memory file descriptor structure.
963  * @param action The requested action.
964  */
965 
966 int file_handler (elxu_device_t *device_p, char const *file_name_p, int action)
967 {
968  dwnld_file_desc_t fileDesc;
969 
970  memset(&fileDesc, 0, sizeof(fileDesc));
971 
972  if (file_handler_init (file_name_p, &fileDesc) < 0)
973  {
974  return -1;
975  }
976 
977  switch (action)
978  {
979  case FW_FILE_DOWNLOAD:
980  if (download_handler(device_p, &fileDesc) != 0) {
981  printf("Error Downloading FW\n");
982  return (-1);
983  }
984  break;
986  if (fileDesc.file_type == FILE_TYPE_UFI)
987  {
988  display_ufi_header(&fileDesc.ufi_hdr);
989  display_ufi_image_hdr(&fileDesc.img_hdr);
990  display_ufi_flash_directory(&fileDesc);
991  }
992  else
993  {
994  printf ("file-format command is only supported for UFI files.\n");
995  }
996  close (fileDesc.fd);
997  zfree(fileDesc.ufi_flash_hdr);
998 
999  break;
1000  case FW_FILE_VERIFY:
1001  if (is_lancer(device_p) || is_prism(device_p))
1002  {
1003  printf("Firmware compare is not supported for Lancer/Prism Family Products.\n");
1004 
1005  }
1006  else if(fileDesc.file_type == FILE_TYPE_UFI)
1007  {
1008  if (hba_image_section_fw_verify(device_p, &fileDesc) < 0)
1009  {
1010  printf("Error Verifying Firmware\n");
1011  }
1012  }
1013  else
1014  {
1015  printf("Firmware compare is only supported for UFI files.\n");
1016  }
1017  break;
1018  default:
1019  printf ("Invalid Action %d \n", action);
1020  return -1;
1021  }
1022  return (0);
1023 }
1024 
1025 /**
1026 * @page flash_parsing Flash File Parsing (Using “file-info”)
1027 *
1028 * The elxsdkutil uses the File Information CLI command (@ref cmd_file_info "file-info")
1029 * to parse a .ufi flash file
1030 * to determine its contents, based on the header format and file layout. It is implemented
1031 * by the file_handler() function in the elxu_dwnld.c module.
1032 *
1033 *
1034 * @page flash_access Flash Access
1035 *
1036 * The elxsdkutil can download firmware and perform diagnostic dumps. The download
1037 * and dump facilities are implemented in the functions described in the following table.
1038 * <table class="dashboard">
1039 * <tr><th>Function Name</th><th>Description</th></tr>
1040 * <tr><td>download_ufi_image()</td><td>Download a .ufi firmware image to an OCe11102 adapter
1041 * using the file handler in the elxu_dwnld.c module.</td></tr>
1042 * <tr><td>download_lancer_image()</td><td>Download a .grp firmware image to an LPe16000/LPe16002
1043 * adapter data using the file handler in the elxu_dwnld.c
1044 * module.</td></tr>
1045 * <tr><td>fat_upload()</td><td>Upload the OCe11102 FAT using the file handler in the
1046 * elxu_dump.c module.</td></tr>
1047 * <tr><td>ext_fat_capabilities_upld()</td><td>Upload the OCe11102 extended FAT capabilities data using
1048 * the file handler in the elxu_dump.c module.</td></tr>
1049 * <tr><td>ext_fat_snapshot_upload()</td><td>Upload the OCe11102 extended FAT snapshot using the file
1050 * handler in the elxu_dump.c module.</td></tr>
1051 * <tr><td>lancer_hba_dump_upload()</td><td>Upload the LPe16000/LPe16002 adapter data using the file
1052 * handler in the elxu_dump.c module.</td></tr>
1053 * </table>
1054 *
1055 */
#define SWAP_4BYTES(x)
Definition: elxu_dwnld.h:41
char * trimmed_string(uint8_t *string)
Trim trailing non-printable characters from a string.
Definition: elxu_common.c:437
int elxu_device_exec(elxu_device_t *device, char *name, void *arg_in, int arg_in_len, void *arg_out, int arg_out_len)
Execute a management function on a device.
Definition: elxu_device.c:952
uint32_t checkSum
Definition: elxu_ufi.h:67
static fFormat_t retrieve_file_format(uint8_t *buf_p, int len)
Returns the file type.
Definition: elxu_dwnld.c:73
static void display_ufi_header(ufi_file_header_t *ufi_hdr_p)
Displays content of UFI file header structure.
Definition: elxu_dwnld.c:261
#define UFI_FILE_HEADER_LENGTH
Definition: elxu_ufi.h:107
static int download_lancer_image(elxu_device_t *device_p, dwnld_file_desc_t *fdsc_p)
Lancer firmware download.
Definition: elxu_dwnld.c:651
#define PATTERN_SIZE
Definition: elxu_dwnld.c:922
#define FILE_TYPE_UFI
Definition: elxu_dwnld.h:70
static void display_ufi_image_hdr(ufi_image_header_t *img_hdr_p)
Displays content of UFI image header structure.
Definition: elxu_dwnld.c:362
void * zmalloc(uint32_t len)
Allocates and zeroes memory to be used.
Definition: elxu_common.c:63
#define HBA_FILE_LANCER
Definition: elxu_dwnld.h:65
char file_name[128]
Definition: elxu_dwnld.h:60
int ufi_image_upload(elxu_device_t *device, uint32_t op_type, uint8_t *buffer, uint32_t bufferLength)
Upload UFI flash image component.
Definition: elxu_sky.c:87
void zfree(void *p)
Frees memory that has been allocated.
Definition: elxu_common.c:80
int is_lancer(elxu_device_t *device_p)
Return true IFF the HBA is a Lancer.
Definition: elxu_device.c:1236
Definition: elxu_ufi.h:61
static int file_handler_init(const char *filename_p, dwnld_file_desc_t *fdesc_p)
Initializes files descriptor structure.
Definition: elxu_dwnld.c:125
#define UNSUPPORTED_FW_IMAGE
Definition: elxu_dwnld.c:59
uint32_t asic_id
Definition: elxu_device.h:87
uint8_t build_version[24]
Definition: elxu_ufi.h:55
uint32_t maxSize
Definition: elxu_ufi.h:65
fFormat_t
Definition: elxu_dwnld.h:51
static int download_skyhawk_image(elxu_device_t *device_p, dwnld_file_desc_t *fdsc_p)
Skyhawk firmware download.
Definition: elxu_dwnld.c:384
#define HBA_FILE_PRISM
Definition: elxu_dwnld.h:67
#define MGMT_FLASHROM_OPCODE_IMAGE_CRC
Definition: elxu_sli4.h:464
flash_directory_entry_t entries[NUM_FLASHDIR_ENTRIES]
Definition: elxu_ufi.h:90
uint16_t opType
Definition: elxu_ufi.h:69
struct stat st
Definition: elxu_dwnld.h:63
uint32_t imageLength
Definition: elxu_ufi.h:101
uint8_t version[FLASH_DIRECTORY_ENTRY_VERSION_SIZE]
Definition: elxu_ufi.h:72
uint8_t signature[52]
Definition: elxu_ufi.h:49
uint32_t ufi_version
Definition: elxu_ufi.h:50
void display_ufi_flash_directory(dwnld_file_desc_t *fdesc)
Displays content of UFI flash directory header.
Definition: elxu_dwnld.c:309
uint32_t checksum
Definition: elxu_ufi.h:52
static int download_lancer_object_file(elxu_device_t *device_p, const char *object_p, dwnld_file_desc_t *fdsc_p)
Lancer file object.
Definition: elxu_dwnld.c:577
int mbox_read_flashrom(elxu_device_t *device, uint32_t opcode, uint32_t optype, uint32_t offset, void *outbuf, uint32_t outbufLength)
Issue read flashrom mailbox command.
Definition: elxu_mbox.c:1339
uint32_t imageChecksum
Definition: elxu_ufi.h:102
#define FW_UPDATE_RESTRICTED
Definition: elxu_dwnld.c:58
char * decode_entry_type(uint32_t entry_type)
Return the name of a UFI entry type.
Definition: elxu_common.c:474
static uint16_t get_op_type(uint8_t entry_type)
Determine mailbox op_type from UFI entry_type.
Definition: elxu_dwnld.c:893
int is_skyhawk(elxu_device_t *device_p)
Return true IFF the HBA is a Skyhawk.
Definition: elxu_device.c:1219
uint32_t file_len
Definition: elxu_ufi.h:51
flash_directory_t * ufi_flash_hdr
Definition: elxu_dwnld.h:76
uint32_t numImages
Definition: elxu_ufi.h:84
uint32_t formatRevNumber
Definition: elxu_ufi.h:81
#define MALLOC_FAILED
Definition: elxu.h:42
uint32_t entryType
Definition: elxu_ufi.h:63
uint32_t offset
Definition: elxu_ufi.h:64
uint32_t imageId
Definition: elxu_ufi.h:99
int ufi_image_download(elxu_device_t *device, uint32_t op_type, uint8_t *buffer, uint32_t bufferLength)
Download UFI flash image component.
Definition: elxu_sky.c:67
static int hba_image_section_fw_verify(elxu_device_t *device_p, dwnld_file_desc_t *fdsc_p)
flash and file data comparison functionality.
Definition: elxu_dwnld.c:739
uint32_t imageSize
Definition: elxu_ufi.h:66
uint8_t asic_support
Definition: elxu_ufi.h:56
uint8_t imageVer[FW_VER_LEN]
Definition: elxu_ufi.h:104
int file_handler(elxu_device_t *device_p, char const *file_name_p, int action)
File manipulating functionality.
Definition: elxu_dwnld.c:966
uint32_t imageOffset
Definition: elxu_ufi.h:100
int is_prism(elxu_device_t *device_p)
Return true IFF the HBA is a Prism.
Definition: elxu_device.c:1270
ufi_image_header_t img_hdr
Definition: elxu_dwnld.h:75
uint32_t antidote
Definition: elxu_ufi.h:53
#define HBA_FILE_SKYHAWK
Definition: elxu_dwnld.h:66
static off_t find_ufi_dir(int fd)
Definition: elxu_dwnld.c:924
static int download_handler(elxu_device_t *device_p, dwnld_file_desc_t *fdsc_p)
Firmware download.
Definition: elxu_dwnld.c:685
int is_calypso(elxu_device_t *device_p)
Return true IFF the HBA is a Calypso.
Definition: elxu_device.c:1287
ufi_file_header_t ufi_hdr
Definition: elxu_dwnld.h:74
uint32_t numOfImgs
Definition: elxu_ufi.h:54