1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Emulex. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 28 #include <emlxs.h> 29 30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */ 31 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C); 32 33 #define MAX_BOOTID 10 34 35 static uint32_t emlxs_erase_fcode_flash(emlxs_hba_t *hba); 36 37 static uint32_t emlxs_write_fcode_flash(emlxs_hba_t *hba, 38 PIMAGE_HDR ImageHdr, caddr_t Buffer); 39 40 static int32_t emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms, 41 uint32_t BufferSize, PAIF_HDR AifHeader, 42 int32_t DwcFile); 43 static uint32_t emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, 44 uint32_t Size, emlxs_fw_image_t *fw_image); 45 static void emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, 46 uint32_t Type, uint32_t RegionId, uint32_t WordCnt, 47 uint32_t BaseAddr); 48 static uint32_t emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr, 49 caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms, 50 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize, 51 PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile); 52 static uint32_t emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, 53 uint32_t len, uint32_t offline, 54 emlxs_fw_image_t *fw_image); 55 static uint32_t emlxs_proc_abs_2mb(emlxs_hba_t *hba, PAIF_HDR AifHdr, 56 caddr_t EntireBuffer, uint32_t FileType, 57 uint32_t BWCflag, uint32_t extType); 58 static void emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base, 59 uint32_t DlByteCount, uint32_t Function, 60 uint32_t Complete, uint32_t DataOffset, uint32_t AreaId, 61 uint8_t MbxCmd, uint32_t StepCmd); 62 static uint32_t emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr, 63 uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms); 64 static uint32_t emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, caddr_t Buffer, 65 uint32_t BufferSize, PAIF_HDR AifHeader, 66 PWAKE_UP_PARMS AbsWakeUpParms, uint32_t BWCflag, 67 uint32_t extType, uint32_t *numBootImage); 68 static uint32_t emlxs_update_exp_rom(emlxs_hba_t *hba, 69 PWAKE_UP_PARMS WakeUpParms); 70 extern uint32_t emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize, 71 uint32_t *MaxIbusSize); 72 static void emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base, 73 uint32_t DlByteCount, uint32_t Function, 74 uint32_t Complete, uint32_t BdeAddress, 75 uint32_t BdeSize, PROG_ID *ProgId); 76 static void emlxs_format_update_parms(MAILBOXQ *mbq, 77 PWAKE_UP_PARMS WakeUpParms); 78 static void emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq, 79 uint32_t region_id, uint32_t size); 80 static uint32_t emlxs_update_wakeup_parms(emlxs_hba_t *hba, 81 PWAKE_UP_PARMS AbsWakeUpParms, 82 PWAKE_UP_PARMS WakeUpParms); 83 static uint32_t emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, 84 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id, 85 uint32_t proc_erom); 86 static uint32_t emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, 87 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 88 static uint32_t emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, 89 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 90 static uint32_t emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, 91 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 92 static uint32_t emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, 93 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 94 static uint32_t emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, 95 PWAKE_UP_PARMS WakeUpParms, PROG_ID *id); 96 static uint32_t emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr, 97 caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms, 98 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize); 99 static uint32_t emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList); 100 101 static uint32_t emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr); 102 103 static void emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr); 104 105 static void emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image); 106 107 static uint32_t emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize); 108 109 static uint32_t emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer, 110 uint32_t BufferSize, PAIF_HDR AifHeader); 111 static uint32_t emlxs_type_check(uint32_t type); 112 113 static uint32_t emlxs_kern_check(emlxs_hba_t *hba, uint32_t version); 114 115 static uint32_t emlxs_stub_check(emlxs_hba_t *hba, uint32_t version); 116 117 static uint32_t emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version); 118 119 static uint32_t emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version); 120 121 static uint32_t emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version); 122 123 static uint32_t emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version); 124 125 static uint32_t emlxs_bios_check(emlxs_hba_t *hba, uint32_t version); 126 127 static uint32_t emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version); 128 129 static uint32_t emlxs_validate_version(emlxs_hba_t *hba, 130 emlxs_fw_file_t *file, uint32_t id, uint32_t type, 131 char *file_type); 132 static uint32_t emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, 133 uint32_t len, emlxs_be_fw_image_t *fw_image); 134 static int32_t emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer, 135 emlxs_be_fw_file_t *file, 136 MAILBOXQ *mbq, MATCHMAP *mp); 137 static int32_t emlxs_sli4_verify_crc(emlxs_hba_t *hba, 138 emlxs_be_fw_file_t *file, 139 MAILBOXQ *mbq, MATCHMAP *mp); 140 static int32_t emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer, 141 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp); 142 static int32_t emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, 143 uint32_t len, uint32_t offline); 144 145 /* ************************************************************************* */ 146 147 extern int32_t 148 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, 149 uint32_t offline) 150 { 151 emlxs_port_t *port = &PPORT; 152 uint32_t *Uptr; 153 IMAGE_HDR ImageHdr; 154 AIF_HDR AifHdr; 155 uint32_t ImageType; 156 WAKE_UP_PARMS WakeUpParms; 157 WAKE_UP_PARMS AbsWakeUpParms; 158 uint32_t MaxRbusSramSize; 159 uint32_t MaxIbusSramSize; 160 int32_t AbsChangeParams = 0; 161 int32_t DwcFile = FALSE; 162 uint32_t rval = 0; 163 emlxs_fw_image_t fw_image; 164 uint32_t i; 165 166 #ifdef EMLXS_LITTLE_ENDIAN 167 caddr_t local_buffer; 168 uint32_t *bptr1; 169 uint32_t *bptr2; 170 #endif /* EMLXS_LITTLE_ENDIAN */ 171 172 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 173 rval = emlxs_sli4_fw_download(hba, buffer, len, offline); 174 return (rval); 175 } 176 177 if (buffer == NULL || len == 0) { 178 return (EMLXS_IMAGE_BAD); 179 } 180 181 #ifdef EMLXS_LITTLE_ENDIAN 182 /* We need to swap the image buffer before we start */ 183 184 /* 185 * Use KM_SLEEP to allocate a temporary buffer 186 */ 187 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP); 188 189 /* Perform a 32 bit swap of the image */ 190 bptr1 = (uint32_t *)local_buffer; 191 bptr2 = (uint32_t *)buffer; 192 for (i = 0; i < (len / 4); i++) { 193 *bptr1 = LE_SWAP32(*bptr2); 194 bptr1++; 195 bptr2++; 196 } 197 198 /* Replace the original buffer */ 199 buffer = local_buffer; 200 #endif /* EMLXS_LITTLE_ENDIAN */ 201 202 bzero(&fw_image, sizeof (emlxs_fw_image_t)); 203 for (i = 0; i < MAX_PROG_TYPES; i++) { 204 (void) strcpy(fw_image.prog[i].label, "none"); 205 } 206 207 /* Validate image */ 208 if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) { 209 goto done; 210 } 211 212 /* Get image type */ 213 Uptr = (uint32_t *)buffer; 214 ImageType = *Uptr; 215 216 /* 217 * Pegasus and beyond FW download is done differently 218 * for absolute download. 219 */ 220 221 /* Check for absolute image */ 222 if ((ImageType == NOP_IMAGE_TYPE) && 223 !(hba->model_info.chip & 224 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 225 /* 226 * Because 2Mb flash download file format is different from 227 * 512k, it needs to be handled differently 228 */ 229 if (rval = emlxs_start_abs_download_2mb(hba, buffer, len, 230 offline, &fw_image)) { 231 goto done; 232 } 233 234 /* Offline already handled */ 235 offline = 0; 236 237 goto SLI_DOWNLOAD_EXIT; 238 } 239 240 /* Pre-pegasus adapters only */ 241 242 /* Check for absolute image */ 243 else if (ImageType == NOP_IMAGE_TYPE) { 244 bcopy(buffer, &AifHdr, sizeof (AIF_HDR)); 245 bzero((void *)&ImageHdr, sizeof (IMAGE_HDR)); 246 247 if (AifHdr.ImageBase && (AifHdr.ImageBase == 0x20000)) { 248 DwcFile = TRUE; 249 } 250 251 AbsChangeParams = emlxs_build_parms(buffer, 252 &AbsWakeUpParms, len, &AifHdr, DwcFile); 253 } else { /* (ImageType != NOP_IMAGE_TYPE) Relative image */ 254 255 bzero((void *)&AifHdr, sizeof (AIF_HDR)); 256 bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR)); 257 } 258 259 /* 260 * Everything checks out, now to just do it 261 */ 262 263 if (offline) { 264 if (emlxs_offline(hba) != FC_SUCCESS) { 265 offline = 0; 266 267 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 268 "Unable to take adapter offline."); 269 270 rval = EMLXS_OFFLINE_FAILED; 271 272 goto SLI_DOWNLOAD_EXIT; 273 } 274 275 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) { 276 offline = 0; 277 278 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 279 "Unable to restart adapter."); 280 281 rval = EMLXS_OFFLINE_FAILED; 282 283 goto SLI_DOWNLOAD_EXIT; 284 } 285 } 286 287 if (ImageHdr.Id.Type == SBUS_FCODE) { 288 /* Erase Flash */ 289 if (emlxs_erase_fcode_flash(hba)) { 290 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 291 "Unable to erase flash."); 292 293 rval = EMLXS_IMAGE_FAILED; 294 295 goto SLI_DOWNLOAD_EXIT; 296 } 297 298 /* Write FCODE */ 299 if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) { 300 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 301 "Unable to write flash."); 302 303 rval = EMLXS_IMAGE_FAILED; 304 305 goto SLI_DOWNLOAD_EXIT; 306 } 307 308 } else { /* !SBUS_FCODE */ 309 310 311 if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) { 312 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 313 "Unable to get parameters."); 314 315 rval = EMLXS_IMAGE_FAILED; 316 317 goto SLI_DOWNLOAD_EXIT; 318 } 319 320 if (emlxs_get_max_sram(hba, &MaxRbusSramSize, 321 &MaxIbusSramSize)) { 322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 323 "Unable to get RAM size."); 324 325 rval = EMLXS_IMAGE_FAILED; 326 327 goto SLI_DOWNLOAD_EXIT; 328 } 329 330 if (ImageType == NOP_IMAGE_TYPE) { 331 if (emlxs_start_abs_download(hba, &AifHdr, buffer, 332 &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize, 333 (AbsChangeParams) ? &AbsWakeUpParms : NULL, 334 DwcFile)) { 335 EMLXS_MSGF(EMLXS_CONTEXT, 336 &emlxs_download_failed_msg, 337 "Failed to program flash."); 338 339 rval = EMLXS_IMAGE_FAILED; 340 341 goto SLI_DOWNLOAD_EXIT; 342 } 343 344 } else { 345 346 if (emlxs_start_rel_download(hba, &ImageHdr, buffer, 347 &WakeUpParms, MaxRbusSramSize, MaxIbusSramSize)) { 348 EMLXS_MSGF(EMLXS_CONTEXT, 349 &emlxs_download_failed_msg, 350 "Failed to program flash."); 351 352 rval = EMLXS_IMAGE_FAILED; 353 354 goto SLI_DOWNLOAD_EXIT; 355 } 356 } 357 358 } /* !SBUS_FCODE */ 359 360 361 SLI_DOWNLOAD_EXIT: 362 363 if (offline) { 364 (void) emlxs_online(hba); 365 } 366 367 if (rval == 0) { 368 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg, 369 "Status good."); 370 } 371 372 done: 373 374 #ifdef EMLXS_LITTLE_ENDIAN 375 /* Free the local buffer */ 376 kmem_free(local_buffer, len); 377 #endif /* EMLXS_LITTLE_ENDIAN */ 378 379 return (rval); 380 381 } /* emlxs_fw_download */ 382 383 384 static void 385 emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size) 386 { 387 while (size--) { 388 *buffer++ = value; 389 } 390 391 } /* emlxs_memset () */ 392 393 394 static int32_t 395 emlxs_sli4_flash_image(emlxs_hba_t *hba, caddr_t buffer, 396 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp) 397 { 398 emlxs_port_t *port = &PPORT; 399 uint8_t *image_ptr; 400 uint32_t *wptr; 401 uint8_t *payload; 402 MAILBOX4 *mb; 403 IOCTL_COMMON_FLASHROM *flashrom; 404 mbox_req_hdr_t *hdr_req; 405 uint32_t image_size; 406 uint32_t block_size; 407 uint32_t xfer_size; 408 uint32_t block_offset; 409 uint32_t count; 410 uint32_t rval = 0; 411 412 if (file->image_size == 0) { 413 return (0); 414 } 415 416 image_ptr = (uint8_t *)buffer + file->image_offset; 417 image_size = file->image_size; 418 block_size = file->block_size; 419 block_offset = 0; 420 mb = (MAILBOX4*)mbq; 421 422 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 423 "%s: Downloading...", file->label); 424 425 while (block_size) { 426 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 427 bzero((void *) mp->virt, mp->size); 428 429 xfer_size = min(BE_MAX_XFER_SIZE, block_size); 430 431 mb->un.varSLIConfig.be.embedded = 0; 432 mbq->nonembed = (uint8_t *)mp; 433 mbq->mbox_cmpl = NULL; 434 435 mb->mbxCommand = MBX_SLI_CONFIG; 436 mb->mbxOwner = OWN_HOST; 437 438 hdr_req = (mbox_req_hdr_t *)mp->virt; 439 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 440 hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM; 441 hdr_req->timeout = 0; 442 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + 443 xfer_size; 444 445 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); 446 flashrom->params.opcode = ((block_size == xfer_size)? 447 MGMT_FLASHROM_OPCODE_FLASH:MGMT_FLASHROM_OPCODE_SAVE); 448 flashrom->params.optype = file->type; 449 flashrom->params.data_buffer_size = xfer_size; 450 flashrom->params.offset = block_offset; 451 452 /* Build data buffer payload */ 453 payload = (uint8_t *)(&flashrom->params.data_buffer); 454 emlxs_memset(payload, 0xff, xfer_size); 455 456 /* Copy remaining image into payload */ 457 if (image_size) { 458 count = min(image_size, xfer_size); 459 BE_SWAP32_BCOPY(image_ptr, payload, count); 460 image_size -= count; 461 image_ptr += count; 462 } 463 464 /* Set last two words of last payload with */ 465 /* image size and block crc */ 466 if (flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) { 467 wptr = (uint32_t *)&payload[(xfer_size - 8)]; 468 wptr[0] = file->image_size; 469 wptr[1] = file->block_crc; 470 } 471 472 /* Send write request */ 473 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 474 MBX_SUCCESS) { 475 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 476 "%s: Unable to download image. status=%x", 477 file->label, mb->mbxStatus); 478 rval = EMLXS_IMAGE_FAILED; 479 goto done; 480 } 481 482 block_size -= xfer_size; 483 block_offset += xfer_size; 484 } 485 486 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 487 "%s: Download complete.", file->label); 488 done: 489 490 return (rval); 491 492 } /* emlxs_sli4_flash_image() */ 493 494 495 static int32_t 496 emlxs_sli4_verify_image(emlxs_hba_t *hba, caddr_t buffer, 497 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp) 498 { 499 emlxs_port_t *port = &PPORT; 500 uint8_t *image_ptr; 501 uint32_t *wptr; 502 uint32_t *wptr1; 503 uint8_t *payload; 504 MAILBOX4 *mb; 505 IOCTL_COMMON_FLASHROM *flashrom; 506 mbox_req_hdr_t *hdr_req; 507 uint32_t xfer_size; 508 uint32_t block_size; 509 uint32_t block_offset; 510 uint32_t rval = 0; 511 uint32_t i; 512 char signature[BE_SIGNATURE_SIZE]; 513 uint32_t ufi_plus = 0; 514 515 /* Check for special deflated format */ 516 (void) sprintf(signature, "%s+", BE_SIGNATURE); 517 if (strncmp(signature, buffer, 518 sizeof (signature)-1) == 0) { 519 ufi_plus = 1; 520 } 521 522 image_ptr = (uint8_t *)buffer + file->image_offset; 523 block_size = (ufi_plus)? file->image_size: file->block_size; 524 block_offset = 0; 525 mb = (MAILBOX4*)mbq; 526 527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 528 "%s: Verifying image...", file->label); 529 530 while (block_size) { 531 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 532 bzero((void *) mp->virt, mp->size); 533 534 xfer_size = min(BE_MAX_XFER_SIZE, block_size); 535 536 mb->un.varSLIConfig.be.embedded = 0; 537 mbq->nonembed = (uint8_t *)mp; 538 mbq->mbox_cmpl = NULL; 539 540 mb->mbxCommand = MBX_SLI_CONFIG; 541 mb->mbxOwner = OWN_HOST; 542 543 hdr_req = (mbox_req_hdr_t *)mp->virt; 544 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 545 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM; 546 hdr_req->timeout = 0; 547 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + 548 xfer_size; 549 550 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); 551 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT; 552 flashrom->params.optype = file->type; 553 flashrom->params.data_buffer_size = xfer_size; 554 flashrom->params.offset = block_offset; 555 556 /* Send read request */ 557 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 558 MBX_SUCCESS) { 559 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 560 "%s: Unable to read image. status=%x", 561 file->label, mb->mbxStatus); 562 563 rval = EMLXS_IMAGE_FAILED; 564 goto done; 565 } 566 567 payload = (uint8_t *)(&flashrom->params.data_buffer); 568 569 BE_SWAP32_BUFFER(payload, xfer_size); 570 571 wptr = (uint32_t *)image_ptr; 572 wptr1 = (uint32_t *)payload; 573 for (i = 0; i < xfer_size; i += 4, wptr++, wptr1++) { 574 if (*wptr != *wptr1) { 575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 576 "%s: Image mismatch. [%08x] %x, %x", 577 file->label, i, 578 BE_MAX_XFER_SIZE, xfer_size); 579 580 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 581 "%08x: %08x %08x %08x %08x %08x " \ 582 "%08x %08x %08x", 583 i, wptr[0], wptr[1], wptr[2], 584 wptr[3], wptr[4], wptr[5], wptr[6], 585 wptr[7]); 586 587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 588 "%08x: %08x %08x %08x %08x %08x " \ 589 "%08x %08x %08x", 590 i, wptr1[0], wptr1[1], wptr1[2], 591 wptr1[3], wptr1[4], wptr1[5], wptr1[6], 592 wptr1[7]); 593 594 rval = EMLXS_IMAGE_FAILED; 595 goto done; 596 } 597 } 598 599 bcopy((uint8_t *)(&flashrom->params.data_buffer), image_ptr, 600 xfer_size); 601 602 block_size -= xfer_size; 603 block_offset += xfer_size; 604 image_ptr += xfer_size; 605 } 606 607 /* Verify CRC */ 608 rval = emlxs_sli4_verify_crc(hba, file, mbq, mp); 609 610 done: 611 612 if (rval == 0) { 613 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 614 "%s: Image verified.", file->label); 615 } 616 617 return (rval); 618 619 } /* emlxs_sli4_verify_image() */ 620 621 622 static int32_t 623 emlxs_sli4_verify_crc(emlxs_hba_t *hba, 624 emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp) 625 { 626 emlxs_port_t *port = &PPORT; 627 uint32_t *wptr; 628 uint8_t *payload; 629 MAILBOX4 *mb; 630 IOCTL_COMMON_FLASHROM *flashrom; 631 mbox_req_hdr_t *hdr_req; 632 uint32_t xfer_size; 633 uint32_t block_offset; 634 uint32_t rval = 0; 635 uint32_t value; 636 637 xfer_size = 8; 638 block_offset = file->block_size - xfer_size; 639 mb = (MAILBOX4*)mbq; 640 641 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 642 "%s: Verifying CRC...", file->label); 643 644 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 645 bzero((void *) mp->virt, mp->size); 646 647 mb->un.varSLIConfig.be.embedded = 0; 648 mbq->nonembed = (uint8_t *)mp; 649 mbq->mbox_cmpl = NULL; 650 651 mb->mbxCommand = MBX_SLI_CONFIG; 652 mb->mbxOwner = OWN_HOST; 653 654 hdr_req = (mbox_req_hdr_t *)mp->virt; 655 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 656 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM; 657 hdr_req->timeout = 0; 658 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + 659 xfer_size; 660 661 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); 662 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT; 663 flashrom->params.optype = file->type; 664 flashrom->params.data_buffer_size = xfer_size; 665 flashrom->params.offset = block_offset; 666 667 /* Send read request */ 668 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 669 MBX_SUCCESS) { 670 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 671 "%s: Unable to read CRC. status=%x", 672 file->label, mb->mbxStatus); 673 674 rval = EMLXS_IMAGE_FAILED; 675 goto done; 676 } 677 678 payload = (uint8_t *)(&flashrom->params.data_buffer); 679 wptr = (uint32_t *)(payload + xfer_size - 8); 680 681 /* Verify image size */ 682 value = *wptr++; 683 if (value != file->image_size) { 684 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 685 "%s: Image size mismatch. %08x != %08x", 686 file->label, value, file->image_size); 687 688 rval = EMLXS_IMAGE_FAILED; 689 goto done; 690 } 691 692 /* Verify block crc */ 693 value = *wptr; 694 if (value != file->block_crc) { 695 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 696 "%s: CRC mismatch. %08x != %08x", 697 file->label, value, file->block_crc); 698 rval = EMLXS_IMAGE_FAILED; 699 } 700 701 done: 702 703 if (rval == 0) { 704 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 705 "%s: CRC verified.", file->label); 706 } 707 708 return (rval); 709 710 } /* emlxs_sli4_verify_crc() */ 711 712 713 extern int32_t 714 emlxs_sli4_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw) 715 { 716 emlxs_port_t *port = &PPORT; 717 MAILBOXQ *mbq = NULL; 718 MATCHMAP *mp = NULL; 719 MAILBOX4 *mb; 720 uint32_t *wptr; 721 uint8_t *payload; 722 IOCTL_COMMON_FLASHROM *flashrom; 723 mbox_req_hdr_t *hdr_req; 724 uint32_t xfer_size; 725 uint32_t block_offset; 726 uint32_t rval = 0; 727 728 bzero((void *) fw, sizeof (emlxs_firmware_t)); 729 730 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 731 KM_SLEEP)) == NULL) { 732 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 733 "read_fw_version: Unable to allocate mailbox buffer."); 734 735 rval = 1; 736 goto done; 737 } 738 739 if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) + 740 sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) { 741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 742 "read_fw_version: Unable to allocate payload buffer."); 743 744 rval = EMLXS_IMAGE_FAILED; 745 goto done; 746 } 747 748 mb = (MAILBOX4*)mbq; 749 750 /* Read CRC and size */ 751 xfer_size = 8; 752 block_offset = 0x140000 - xfer_size; 753 754 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 755 bzero((void *) mp->virt, mp->size); 756 757 mb->un.varSLIConfig.be.embedded = 0; 758 mbq->nonembed = (uint8_t *)mp; 759 mbq->mbox_cmpl = NULL; 760 761 mb->mbxCommand = MBX_SLI_CONFIG; 762 mb->mbxOwner = OWN_HOST; 763 764 hdr_req = (mbox_req_hdr_t *)mp->virt; 765 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 766 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM; 767 hdr_req->timeout = 0; 768 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + 769 xfer_size; 770 771 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); 772 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT; 773 flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE; 774 flashrom->params.data_buffer_size = xfer_size; 775 flashrom->params.offset = block_offset; 776 777 /* Send read request */ 778 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 779 MBX_SUCCESS) { 780 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 781 "read_fw_version: Unable to read CRC. status=%x", 782 mb->mbxStatus); 783 784 rval = 1; 785 goto done; 786 } 787 788 payload = (uint8_t *)(&flashrom->params.data_buffer); 789 790 wptr = (uint32_t *)payload; 791 fw->size = *wptr++; /* image size */ 792 fw->sli4 = *wptr; /* block crc */ 793 fw->kern = *wptr; 794 fw->stub = *wptr; 795 796 /* Read version label */ 797 xfer_size = 32; 798 block_offset = 0x30; 799 800 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 801 bzero((void *) mp->virt, mp->size); 802 803 mb->un.varSLIConfig.be.embedded = 0; 804 mbq->nonembed = (uint8_t *)mp; 805 mbq->mbox_cmpl = NULL; 806 807 mb->mbxCommand = MBX_SLI_CONFIG; 808 mb->mbxOwner = OWN_HOST; 809 810 hdr_req = (mbox_req_hdr_t *)mp->virt; 811 hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON; 812 hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM; 813 hdr_req->timeout = 0; 814 hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) + 815 xfer_size; 816 817 flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1); 818 flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT; 819 flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE; 820 flashrom->params.data_buffer_size = xfer_size; 821 flashrom->params.offset = block_offset; 822 823 /* Send read request */ 824 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != 825 MBX_SUCCESS) { 826 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 827 "read_fw_version: Unable to read version string. status=%x", 828 mb->mbxStatus); 829 830 rval = 1; 831 goto done; 832 } 833 834 payload = (uint8_t *)(&flashrom->params.data_buffer); 835 BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32); 836 837 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg, 838 "FCOE FIRMWARE: size=%x version=%s (0x%08x)", 839 fw->size, fw->label, fw->sli4); 840 841 done: 842 843 if (mbq) { 844 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 845 } 846 847 if (mp) { 848 (void) emlxs_mem_buf_free(hba, mp); 849 } 850 851 return (rval); 852 853 } /* emlxs_sli4_read_fw_version() */ 854 855 856 static uint32_t 857 emlxs_sli4_validate_image(emlxs_hba_t *hba, caddr_t buffer, 858 uint32_t len, emlxs_be_fw_image_t *fw_image) 859 { 860 emlxs_port_t *port = &PPORT; 861 emlxs_sli4_ufi_header_t *ufi_hdr; 862 emlxs_sli4_flash_dir_t *flash_dir; 863 emlxs_sli4_flash_entry_t *entry; 864 uint8_t *bptr; 865 uint32_t *wptr; 866 uint32_t i; 867 uint32_t k; 868 uint32_t mask; 869 uint32_t value; 870 uint32_t image_size; 871 emlxs_be_fw_file_t *file; 872 emlxs_be_fw_file_t *file2; 873 char signature[BE_SIGNATURE_SIZE]; 874 uint32_t ufi_plus = 0; 875 876 bzero(fw_image, sizeof (emlxs_be_fw_image_t)); 877 878 if (hba->model_info.chip != EMLXS_BE_CHIP) { 879 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 880 "Invalid adapter model."); 881 return (EMLXS_IMAGE_INCOMPATIBLE); 882 } 883 884 if (len < (sizeof (emlxs_sli4_ufi_header_t) + 885 sizeof (emlxs_sli4_flash_dir_t))) { 886 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 887 "Image too small. (%d < %d)", 888 len, (sizeof (emlxs_sli4_ufi_header_t) + 889 sizeof (emlxs_sli4_flash_dir_t))); 890 return (EMLXS_IMAGE_BAD); 891 } 892 ufi_hdr = (emlxs_sli4_ufi_header_t *)buffer; 893 894 /* Check if this is a standard UFI image */ 895 if (strncmp(BE_SIGNATURE, ufi_hdr->signature, 896 sizeof (BE_SIGNATURE)-1) != 0) { 897 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 898 "Invalid image provided."); 899 return (EMLXS_IMAGE_INCOMPATIBLE); 900 } 901 902 /* Check for special deflated format */ 903 (void) sprintf(signature, "%s+", BE_SIGNATURE); 904 if (strncmp(signature, ufi_hdr->signature, 905 sizeof (signature)-1) == 0) { 906 ufi_plus = 1; 907 } 908 909 #ifdef EMLXS_BIG_ENDIAN 910 /* Big Endian Swapping */ 911 /* Swap ufi header */ 912 ufi_hdr->checksum = 913 SWAP32(ufi_hdr->checksum); 914 ufi_hdr->antidote = 915 SWAP32(ufi_hdr->antidote); 916 ufi_hdr->controller.vendor_id = 917 SWAP32(ufi_hdr->controller.vendor_id); 918 ufi_hdr->controller.device_id = 919 SWAP32(ufi_hdr->controller.device_id); 920 ufi_hdr->controller.sub_vendor_id = 921 SWAP32(ufi_hdr->controller.sub_vendor_id); 922 ufi_hdr->controller.sub_device_id = 923 SWAP32(ufi_hdr->controller.sub_device_id); 924 ufi_hdr->file_length = 925 SWAP32(ufi_hdr->file_length); 926 ufi_hdr->chunk_num = 927 SWAP32(ufi_hdr->chunk_num); 928 ufi_hdr->chunk_cnt = 929 SWAP32(ufi_hdr->chunk_cnt); 930 ufi_hdr->image_cnt = 931 SWAP32(ufi_hdr->image_cnt); 932 #endif /* EMLXS_BIG_ENDIAN */ 933 934 if (len != ufi_hdr->file_length) { 935 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 936 "Invalid image size (%d != %d)", 937 len, ufi_hdr->file_length); 938 939 return (EMLXS_IMAGE_BAD); 940 } 941 942 /* Scan for flash dir signature */ 943 bptr = (uint8_t *)buffer; 944 flash_dir = NULL; 945 for (i = 0; i < len; i++, bptr++) { 946 if (strncmp((char *)bptr, BE_DIR_SIGNATURE, 947 sizeof (BE_DIR_SIGNATURE)) == 0) { 948 flash_dir = (emlxs_sli4_flash_dir_t *)bptr; 949 break; 950 } 951 } 952 953 if (!flash_dir) { 954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 955 "Unable to find flash directory."); 956 957 return (EMLXS_IMAGE_BAD); 958 } 959 960 #ifdef EMLXS_BIG_ENDIAN 961 /* Big Endian Swapping */ 962 /* Swap flash dir */ 963 flash_dir->header.format_rev = 964 SWAP32(flash_dir->header.format_rev); 965 flash_dir->header.checksum = 966 SWAP32(flash_dir->header.checksum); 967 flash_dir->header.antidote = 968 SWAP32(flash_dir->header.antidote); 969 flash_dir->header.build_num = 970 SWAP32(flash_dir->header.build_num); 971 flash_dir->header.active_entry_mask = 972 SWAP32(flash_dir->header.active_entry_mask); 973 flash_dir->header.valid_entry_mask = 974 SWAP32(flash_dir->header.valid_entry_mask); 975 flash_dir->header.orig_content_mask = 976 SWAP32(flash_dir->header.orig_content_mask); 977 flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0); 978 flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1); 979 flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2); 980 flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3); 981 flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4); 982 983 for (i = 0; i < BE_CONTROLLER_SIZE; i++) { 984 flash_dir->header.controller[i].vendor_id = 985 SWAP32(flash_dir->header.controller[i].vendor_id); 986 flash_dir->header.controller[i].device_id = 987 SWAP32(flash_dir->header.controller[i].device_id); 988 flash_dir->header.controller[i].sub_vendor_id = 989 SWAP32(flash_dir->header.controller[i].sub_vendor_id); 990 flash_dir->header.controller[i].sub_device_id = 991 SWAP32(flash_dir->header.controller[i].sub_device_id); 992 } 993 994 for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) { 995 996 if (!(flash_dir->header.valid_entry_mask & mask)) { 997 continue; 998 } 999 1000 entry = &flash_dir->entry[i]; 1001 if (entry->image_size == 0) { 1002 continue; 1003 } 1004 1005 flash_dir->entry[i].type = 1006 SWAP32(flash_dir->entry[i].type); 1007 flash_dir->entry[i].offset = 1008 SWAP32(flash_dir->entry[i].offset); 1009 flash_dir->entry[i].pad_size = 1010 SWAP32(flash_dir->entry[i].pad_size); 1011 flash_dir->entry[i].image_size = 1012 SWAP32(flash_dir->entry[i].image_size); 1013 flash_dir->entry[i].checksum = 1014 SWAP32(flash_dir->entry[i].checksum); 1015 flash_dir->entry[i].entry_point = 1016 SWAP32(flash_dir->entry[i].entry_point); 1017 flash_dir->entry[i].resv0 = 1018 SWAP32(flash_dir->entry[i].resv0); 1019 flash_dir->entry[i].resv1 = 1020 SWAP32(flash_dir->entry[i].resv1); 1021 } 1022 #endif /* EMLXS_BIG_ENDIAN */ 1023 1024 /* Build fw_image table */ 1025 for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) { 1026 1027 if (!(flash_dir->header.valid_entry_mask & mask)) { 1028 continue; 1029 } 1030 1031 entry = &flash_dir->entry[i]; 1032 if (entry->image_size == 0) { 1033 continue; 1034 } 1035 1036 switch (entry->type) { 1037 case BE_FLASHTYPE_REDBOOT: 1038 file = &fw_image->file[REDBOOT_FLASHTYPE]; 1039 (void) strcpy(file->label, "REDBOOT"); 1040 file->type = MGMT_FLASHROM_OPTYPE_REDBOOT; 1041 break; 1042 case BE_FLASHTYPE_ISCSI_BIOS: 1043 file = &fw_image->file[ISCSI_BIOS_FLASHTYPE]; 1044 (void) strcpy(file->label, "ISCSI BIOS"); 1045 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS; 1046 break; 1047 case BE_FLASHTYPE_PXE_BIOS: 1048 file = &fw_image->file[PXE_BIOS_FLASHTYPE]; 1049 (void) strcpy(file->label, "PXE BIOS"); 1050 file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS; 1051 break; 1052 case BE_FLASHTYPE_FCOE_BIOS: 1053 file = &fw_image->file[FCOE_BIOS_FLASHTYPE]; 1054 (void) strcpy(file->label, "FCOE BIOS"); 1055 file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS; 1056 break; 1057 case BE_FLASHTYPE_ISCSI_FIRMWARE: 1058 file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE]; 1059 (void) strcpy(file->label, "ISCSI FIRMWARE"); 1060 file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE; 1061 break; 1062 case BE_FLASHTYPE_FCOE_FIRMWARE: 1063 file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE]; 1064 (void) strcpy(file->label, "FCOE FIRMWARE"); 1065 file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE; 1066 break; 1067 case BE_FLASHTYPE_FCOE_BACKUP: 1068 case BE_FLASHTYPE_ISCSI_BACKUP: 1069 continue; 1070 1071 default: 1072 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1073 "Unknown image type found. type=%x", 1074 entry->type); 1075 continue; 1076 } 1077 1078 file->image_size = entry->image_size; 1079 image_size = BE_SWAP32(entry->image_size); 1080 1081 if (ufi_plus) { 1082 file->image_offset = entry->offset; 1083 file->block_size = entry->pad_size; 1084 file->block_crc = entry->checksum; 1085 } else { 1086 file->image_offset = entry->offset + 1087 sizeof (emlxs_sli4_ufi_header_t); 1088 1089 /* Get entry block size and crc */ 1090 k = file->image_offset + file->image_size; 1091 k &= 0xFFFFFFFC; 1092 1093 wptr = (uint32_t *)(buffer + k); 1094 for (; k < len; k += 4) { 1095 if (*wptr++ == image_size) { 1096 /* Calculate block_size */ 1097 file->block_size = (k + 8) - 1098 file->image_offset; 1099 1100 /* Read block_crc */ 1101 value = *wptr; 1102 file->block_crc = BE_SWAP32(value); 1103 1104 break; 1105 } 1106 } 1107 1108 if (k >= len) { 1109 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1110 "%s: End of block not found. offset=%x", 1111 file->label, file->image_offset); 1112 1113 bzero(fw_image, sizeof (emlxs_be_fw_image_t)); 1114 return (EMLXS_IMAGE_BAD); 1115 } 1116 } 1117 1118 /* Make sure image will fit in block specified */ 1119 if (file->image_size + 8 > file->block_size) { 1120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1121 "%s: Image too large for block. image=%x block=%x", 1122 file->label, file->image_size, file->block_size); 1123 1124 bzero(fw_image, sizeof (emlxs_be_fw_image_t)); 1125 return (EMLXS_IMAGE_BAD); 1126 } 1127 1128 /* Automatically create a backup file entry for firmware */ 1129 if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) { 1130 file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE]; 1131 (void) strcpy(file2->label, "FCOE BACKUP"); 1132 file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP; 1133 file2->image_offset = file->image_offset; 1134 file2->image_size = file->image_size; 1135 file2->block_size = file->block_size; 1136 file2->block_crc = file->block_crc; 1137 1138 /* Save FCOE version info */ 1139 bptr = (uint8_t *)buffer + file->image_offset + 0x30; 1140 (void) strncpy(fw_image->label, (char *)bptr, 1141 BE_VERSION_SIZE); 1142 fw_image->version = file->block_crc; 1143 1144 } else if (file->type == 1145 MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) { 1146 file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE]; 1147 (void) strcpy(file2->label, "ISCSI BACKUP"); 1148 file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP; 1149 file2->image_offset = file->image_offset; 1150 file2->image_size = file->image_size; 1151 file2->block_size = file->block_size; 1152 file2->block_crc = file->block_crc; 1153 } 1154 } 1155 1156 if (fw_image->version == 0) { 1157 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1158 "Unable to find FCOE firmware component."); 1159 1160 bzero(fw_image, sizeof (emlxs_be_fw_image_t)); 1161 return (EMLXS_IMAGE_BAD); 1162 } 1163 1164 /* Display contents */ 1165 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1166 "UFI Image: %08x, %s", fw_image->version, fw_image->label); 1167 1168 for (i = 0; i < BE_MAX_FLASHTYPES; i++) { 1169 file = &fw_image->file[i]; 1170 1171 if (file->image_size == 0) { 1172 continue; 1173 } 1174 1175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 1176 "%s: type=%x block=%x image=%x offset=%x crc=%x", 1177 file->label, file->type, file->block_size, 1178 file->image_size, file->image_offset, file->block_crc); 1179 } 1180 1181 return (0); 1182 1183 } /* emlxs_sli4_validate_image() */ 1184 1185 1186 static int32_t 1187 emlxs_sli4_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, 1188 uint32_t offline) 1189 { 1190 emlxs_port_t *port = &PPORT; 1191 uint32_t i; 1192 uint32_t update = 0; 1193 uint32_t rval = 0; 1194 MAILBOXQ *mbq = NULL; 1195 MATCHMAP *mp = NULL; 1196 emlxs_be_fw_image_t fw_image; 1197 emlxs_be_fw_file_t *file; 1198 1199 /* For now we will not take the driver offline during a download */ 1200 offline = 0; 1201 1202 if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) { 1203 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 1204 "Invalid sli_mode. mode=%d", hba->sli_mode); 1205 return (EMLXS_IMAGE_INCOMPATIBLE); 1206 } 1207 1208 if (buffer == NULL || len == 0) { 1209 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1210 "Empty buffer provided. buf=%p size=%d", buffer, len); 1211 return (EMLXS_IMAGE_BAD); 1212 } 1213 1214 /* Validate image */ 1215 if ((rval = emlxs_sli4_validate_image(hba, buffer, len, &fw_image))) { 1216 return (rval); 1217 } 1218 1219 /* Allocate resources */ 1220 1221 if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1222 KM_SLEEP)) == NULL) { 1223 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1224 "Unable to allocate mailbox buffer."); 1225 1226 offline = 0; 1227 rval = EMLXS_IMAGE_FAILED; 1228 goto done; 1229 } 1230 1231 if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) + 1232 sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) { 1233 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1234 "Unable to allocate flash buffer."); 1235 1236 offline = 0; 1237 rval = EMLXS_IMAGE_FAILED; 1238 goto done; 1239 } 1240 1241 /* Check if update is required */ 1242 for (i = 0; i < BE_MAX_FLASHTYPES; i++) { 1243 file = &fw_image.file[i]; 1244 1245 if (file->image_size == 0) { 1246 continue; 1247 } 1248 1249 rval = emlxs_sli4_verify_crc(hba, file, mbq, mp); 1250 1251 if (rval == 0) { 1252 file->image_size = 0; 1253 continue; 1254 } 1255 1256 update++; 1257 } 1258 1259 if (!update) { 1260 offline = 0; 1261 goto done; 1262 } 1263 1264 /* 1265 * Everything checks out, now to just do it 1266 */ 1267 if (offline) { 1268 if (emlxs_offline(hba) != FC_SUCCESS) { 1269 1270 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1271 "Unable to take adapter offline."); 1272 1273 offline = 0; 1274 rval = EMLXS_OFFLINE_FAILED; 1275 goto done; 1276 } 1277 } 1278 1279 /* Download entries which require update */ 1280 for (i = 0; i < BE_MAX_FLASHTYPES; i++) { 1281 file = &fw_image.file[i]; 1282 1283 if (file->image_size == 0) { 1284 continue; 1285 } 1286 1287 rval = emlxs_sli4_flash_image(hba, buffer, file, mbq, mp); 1288 1289 if (rval != 0) { 1290 goto done; 1291 } 1292 } 1293 1294 done: 1295 if (mbq) { 1296 (void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq); 1297 } 1298 1299 if (mp) { 1300 (void) emlxs_mem_buf_free(hba, mp); 1301 } 1302 1303 if (offline) { 1304 (void) emlxs_online(hba); 1305 } 1306 1307 if (rval == 0) { 1308 if (update) { 1309 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg, 1310 "Status good."); 1311 1312 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg, 1313 "Please reboot system or power cycle adapter " 1314 "to activate new firmware: %s", fw_image.label); 1315 1316 } else { 1317 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1318 "No firmware update required."); 1319 } 1320 } 1321 1322 return (rval); 1323 1324 } /* emlxs_sli4_fw_download() */ 1325 1326 1327 extern int32_t 1328 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer, 1329 uint32_t len) 1330 { 1331 emlxs_port_t *port = &PPORT; 1332 MAILBOXQ *mbox = NULL; 1333 MAILBOX *mb; 1334 uint32_t rval = 0; 1335 uint32_t region_id; 1336 uint32_t id; 1337 #ifdef EMLXS_BIG_ENDIAN 1338 caddr_t local_buffer; 1339 uint32_t *bptr1; 1340 uint32_t *bptr2; 1341 uint32_t i; 1342 #endif /* EMLXS_BIG_ENDIAN */ 1343 1344 if (buffer == NULL || len == 0) { 1345 return (EMLXS_IMAGE_BAD); 1346 } 1347 1348 #ifdef EMLXS_BIG_ENDIAN 1349 /* We need to swap the image buffer before we start */ 1350 1351 /* 1352 * Use KM_SLEEP to allocate a temporary buffer 1353 */ 1354 local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP); 1355 1356 /* Perform a 32 bit swap of the image */ 1357 bptr1 = (uint32_t *)local_buffer; 1358 bptr2 = (uint32_t *)buffer; 1359 1360 for (i = 0; i < (len / 4); i++) { 1361 *bptr1 = SWAP32(*bptr2); 1362 bptr1++; 1363 bptr2++; 1364 } 1365 1366 /* Replace the original buffer */ 1367 buffer = local_buffer; 1368 1369 #endif /* EMLXS_BIG_ENDIAN */ 1370 1371 if (len > 128) { 1372 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1373 "Invalid image length: 0x%x > 128", len); 1374 1375 return (EMLXS_IMAGE_BAD); 1376 } 1377 1378 /* Check the region number */ 1379 if ((region > 2) && (region != 0xff)) { 1380 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1381 "Invalid region id: 0x%x", region); 1382 1383 return (EMLXS_IMAGE_BAD); 1384 1385 } 1386 1387 /* Check the image vendor id */ 1388 id = *(int32_t *)buffer; 1389 if ((id & 0xffff) != 0x10df) { 1390 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 1391 "Invalid image id: 0x%x", id); 1392 1393 return (EMLXS_IMAGE_BAD); 1394 } 1395 1396 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1397 KM_NOSLEEP)) == NULL) { 1398 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1399 "Unable to allocate mailbox buffer."); 1400 1401 rval = 1; 1402 1403 goto done; 1404 } 1405 1406 mb = (MAILBOX *)mbox; 1407 1408 /* 1409 * Everything checks out, now to just do it 1410 */ 1411 if (emlxs_offline(hba) != FC_SUCCESS) { 1412 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1413 "Unable to take HBA offline."); 1414 1415 rval = EMLXS_OFFLINE_FAILED; 1416 1417 goto done; 1418 } 1419 1420 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) { 1421 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1422 "Unable to restart adapter."); 1423 1424 rval = EMLXS_OFFLINE_FAILED; 1425 1426 goto done; 1427 } 1428 1429 /* Check if default region is requested */ 1430 if (region == 0xff) { 1431 /* 1432 * Sun-branded Helios and Zypher have different 1433 * default PCI region 1434 */ 1435 if ((hba->model_info.flags & EMLXS_SUN_BRANDED) && 1436 (hba->model_info.chip & 1437 (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) { 1438 region = 2; 1439 } else { 1440 region = 0; 1441 } 1442 } 1443 1444 /* Set region id based on PCI region requested */ 1445 region_id = DEF_PCI_CFG_REGION_ID + region; 1446 1447 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1448 "PCI configuration: PCI%d region=%d id=0x%x size=%d", region, 1449 region_id, id, len); 1450 1451 /* Copy the data buffer to SLIM */ 1452 WRITE_SLIM_COPY(hba, (uint32_t *)buffer, 1453 (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr + 1454 sizeof (MAILBOX)), (len / sizeof (uint32_t))); 1455 1456 #ifdef FMA_SUPPORT 1457 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 1458 != DDI_FM_OK) { 1459 EMLXS_MSGF(EMLXS_CONTEXT, 1460 &emlxs_invalid_access_handle_msg, NULL); 1461 rval = 1; 1462 } 1463 #endif /* FMA_SUPPORT */ 1464 1465 emlxs_format_update_pci_cfg(hba, mbox, region_id, len); 1466 1467 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 1468 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1469 "Unable to update PCI configuration: Mailbox cmd=%x " 1470 "status=%x info=%d", mb->mbxCommand, mb->mbxStatus, 1471 mb->un.varUpdateCfg.rsp_info); 1472 1473 rval = 1; 1474 } 1475 1476 (void) emlxs_online(hba); 1477 1478 if (rval == 0) { 1479 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg, 1480 "Status good."); 1481 } 1482 1483 done: 1484 1485 if (mbox) { 1486 kmem_free(mbox, sizeof (MAILBOXQ)); 1487 } 1488 1489 #ifdef EMLXS_BIG_ENDIAN 1490 /* Free the local buffer */ 1491 kmem_free(local_buffer, len); 1492 #endif /* EMLXS_BIG_ENDIAN */ 1493 1494 return (rval); 1495 1496 } /* emlxs_cfl_download */ 1497 1498 1499 static uint32_t 1500 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr) 1501 { 1502 uint32_t Temp; 1503 uint32_t CkSum; 1504 1505 EndAddr++; 1506 CkSum = SLI_CKSUM_SEED; 1507 1508 CkSum = (CkSum >> 1) | (CkSum << 31); 1509 while (StartAddr != EndAddr) { 1510 CkSum = (CkSum << 1) | (CkSum >> 31); 1511 Temp = *StartAddr; 1512 1513 CkSum ^= Temp; 1514 StartAddr++; 1515 } 1516 1517 return (CkSum << 1) | (CkSum >> 31); 1518 1519 } /* emlxs_valid_cksum() */ 1520 1521 1522 static void 1523 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr) 1524 { 1525 emlxs_port_t *port = &PPORT; 1526 1527 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: "); 1528 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1529 "AIF Header: compress_br = 0x%x", AifHdr->CompressBr); 1530 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1531 "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr); 1532 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1533 "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr); 1534 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1535 "AIF Header: entry_br = 0x%x", AifHdr->EntryBr); 1536 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1537 "AIF Header: area_id = 0x%x", AifHdr->Area_ID); 1538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1539 "AIF Header: rosize = 0x%x", AifHdr->RoSize); 1540 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1541 "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize); 1542 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1543 "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize); 1544 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1545 "AIF Header: dbgtype = 0x%x", AifHdr->DbgType); 1546 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1547 "AIF Header: imagebase = 0x%x", AifHdr->ImageBase); 1548 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1549 "AIF Header: area_size = 0x%x", AifHdr->Area_Size); 1550 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1551 "AIF Header: address_mode = 0x%x", AifHdr->AddressMode); 1552 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1553 "AIF Header: database = 0x%x", AifHdr->DataBase); 1554 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1555 "AIF Header: aversion = 0x%x", AifHdr->AVersion); 1556 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1557 "AIF Header: spare2 = 0x%x", AifHdr->Spare2); 1558 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1559 "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi); 1560 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1561 "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]); 1562 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1563 "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]); 1564 1565 } /* emlxs_disp_aif_header() */ 1566 1567 1568 1569 static void 1570 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image) 1571 { 1572 emlxs_port_t *port = &PPORT; 1573 1574 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: "); 1575 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1576 "Img Header: BlockSize = 0x%x", image->BlockSize); 1577 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1578 "Img Header: PROG_ID Type = 0x%x", image->Id.Type); 1579 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1580 "Img Header: PROG_ID Id = 0x%x", image->Id.Id); 1581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1582 "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver); 1583 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1584 "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev); 1585 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1586 "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp); 1587 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1588 "Img Header: Flags = 0x%x", image->Flags); 1589 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1590 "Img Header: EntryAdr = 0x%x", image->EntryAdr); 1591 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1592 "Img Header: InitAdr = 0x%x", image->InitAdr); 1593 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1594 "Img Header: ExitAdr = 0x%x", image->ExitAdr); 1595 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1596 "Img Header: ImageBase = 0x%x", image->ImageBase); 1597 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1598 "Img Header: ImageSize = 0x%x", image->ImageSize); 1599 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1600 "Img Header: ZinitSize = 0x%x", image->ZinitSize); 1601 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1602 "Img Header: RelocSize = 0x%x", image->RelocSize); 1603 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, 1604 "Img Header: HdrCks = 0x%x", image->HdrCks); 1605 1606 } /* emlxs_dump_image_header() */ 1607 1608 1609 static void 1610 emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type, 1611 uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr) 1612 { 1613 1614 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 1615 MAILBOX4 *mb = (MAILBOX4 *)mbq; 1616 1617 /* Clear the local dump_region */ 1618 bzero(hba->sli.sli4.dump_region.virt, 1619 hba->sli.sli4.dump_region.size); 1620 1621 bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE); 1622 1623 mb->mbxCommand = MBX_DUMP_MEMORY; 1624 mb->un.varDmp4.type = Type; 1625 mb->un.varDmp4.entry_index = BaseAddr; 1626 mb->un.varDmp4.region_id = RegionId; 1627 1628 mb->un.varDmp4.available_cnt = min((WordCount*4), 1629 hba->sli.sli4.dump_region.size); 1630 mb->un.varDmp4.addrHigh = 1631 PADDR_HI(hba->sli.sli4.dump_region.phys); 1632 mb->un.varDmp4.addrLow = 1633 PADDR_LO(hba->sli.sli4.dump_region.phys); 1634 mb->un.varDmp4.rsp_cnt = 0; 1635 1636 mb->mbxOwner = OWN_HOST; 1637 1638 } else { 1639 MAILBOX *mb = (MAILBOX *)mbq; 1640 1641 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1642 1643 mb->mbxCommand = MBX_DUMP_MEMORY; 1644 mb->un.varDmp.type = Type; 1645 mb->un.varDmp.region_id = RegionId; 1646 mb->un.varDmp.word_cnt = WordCount; 1647 mb->un.varDmp.base_adr = BaseAddr; 1648 mb->mbxOwner = OWN_HOST; 1649 } 1650 1651 mbq->mbox_cmpl = NULL; /* no cmpl needed */ 1652 1653 return; 1654 1655 } /* emlxs_format_dump() */ 1656 1657 1658 /* ARGSUSED */ 1659 static uint32_t 1660 emlxs_start_abs_download(emlxs_hba_t *hba, 1661 PAIF_HDR AifHdr, 1662 caddr_t Buffer, 1663 PWAKE_UP_PARMS WakeUpParms, 1664 uint32_t MaxRbusSramSize, 1665 uint32_t MaxIbusSramSize, PWAKE_UP_PARMS AbsWakeUpParms, int32_t DwcFile) 1666 { 1667 emlxs_port_t *port = &PPORT; 1668 uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize; 1669 IMAGE_HDR ImageHdr; 1670 uint32_t *Src; 1671 uint32_t *Dst; 1672 caddr_t DataBuffer = NULL; 1673 MAILBOXQ *mbox; 1674 MAILBOX *mb; 1675 uint32_t rval = 1; 1676 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 1677 uint32_t DlToAddr = AifHdr->ImageBase; 1678 uint32_t DlCount; 1679 uint32_t i; 1680 1681 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1682 "Performing absolute download..."); 1683 1684 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 1685 KM_NOSLEEP)) == NULL) { 1686 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1687 "Unable to allocate data buffer."); 1688 1689 return (rval); 1690 } 1691 1692 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1693 KM_NOSLEEP)) == NULL) { 1694 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1695 "Unable to allocate mailbox buffer."); 1696 1697 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 1698 1699 return (rval); 1700 } 1701 1702 mb = (MAILBOX *)mbox; 1703 1704 Buffer += sizeof (AIF_HDR); 1705 1706 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash..."); 1707 1708 if (DwcFile) { 1709 emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0, 1710 0, 0, NULL); 1711 } else { 1712 emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount, 1713 ERASE_FLASH, 0, 0, 0, NULL); 1714 } 1715 1716 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 1717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1718 "Unable to erase Flash: Mailbox cmd=%x status=%x", 1719 mb->mbxCommand, mb->mbxStatus); 1720 1721 rval = 1; 1722 1723 goto EXIT_ABS_DOWNLOAD; 1724 } 1725 1726 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 1727 "Programming flash..."); 1728 1729 while (DlByteCount) { 1730 1731 if (DlByteCount > SegSize) { 1732 DlCount = SegSize; 1733 } else { 1734 DlCount = DlByteCount; 1735 } 1736 DlByteCount -= DlCount; 1737 1738 Dst = (uint32_t *)DataBuffer; 1739 Src = (uint32_t *)Buffer; 1740 1741 for (i = 0; i < (DlCount / 4); i++) { 1742 *Dst = *Src; 1743 Dst++; 1744 Src++; 1745 } 1746 1747 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 1748 (volatile uint32_t *) 1749 ((volatile char *)hba->sli.sli3.slim_addr + 1750 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t))); 1751 1752 emlxs_format_prog_flash(mbox, DlToAddr, DlCount, 1753 PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL); 1754 1755 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 1756 MBX_SUCCESS) { 1757 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1758 "Unable to program Flash: Mailbox cmd=%x status=%x", 1759 mb->mbxCommand, mb->mbxStatus); 1760 1761 rval = 1; 1762 1763 goto EXIT_ABS_DOWNLOAD; 1764 } 1765 1766 Buffer += DlCount; 1767 DlToAddr += DlCount; 1768 } 1769 1770 #ifdef FMA_SUPPORT 1771 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 1772 != DDI_FM_OK) { 1773 EMLXS_MSGF(EMLXS_CONTEXT, 1774 &emlxs_invalid_access_handle_msg, NULL); 1775 1776 rval = 1; 1777 1778 goto EXIT_ABS_DOWNLOAD; 1779 } 1780 #endif /* FMA_SUPPORT */ 1781 1782 bzero((caddr_t)&ImageHdr, sizeof (IMAGE_HDR)); 1783 ImageHdr.Id.Type = FUNC_FIRMWARE; 1784 1785 switch (MaxRbusSramSize) { 1786 case REDUCED_RBUS_SRAM_CFG: 1787 ImageHdr.Id.Id = REDUCED_SRAM_CFG_PROG_ID; 1788 break; 1789 case FULL_RBUS_SRAM_CFG: 1790 ImageHdr.Id.Id = FULL_SRAM_CFG_PROG_ID; 1791 break; 1792 default: 1793 ImageHdr.Id.Id = OTHER_SRAM_CFG_PROG_ID; 1794 break; 1795 } 1796 1797 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params..."); 1798 1799 if (AbsWakeUpParms) { 1800 rval = 1801 emlxs_update_wakeup_parms(hba, AbsWakeUpParms, 1802 WakeUpParms); 1803 } else { 1804 rval = 1805 emlxs_update_boot_wakeup_parms(hba, WakeUpParms, 1806 &ImageHdr.Id, 1); 1807 } 1808 1809 EXIT_ABS_DOWNLOAD: 1810 if (DataBuffer) { 1811 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 1812 } 1813 1814 if (mbox) { 1815 kmem_free(mbox, sizeof (MAILBOXQ)); 1816 } 1817 1818 return (rval); 1819 1820 } /* emlxs_start_abs_download() */ 1821 1822 1823 /* ARGSUSED */ 1824 static void 1825 emlxs_format_prog_flash(MAILBOXQ *mbq, 1826 uint32_t Base, 1827 uint32_t DlByteCount, 1828 uint32_t Function, 1829 uint32_t Complete, 1830 uint32_t BdeAddress, uint32_t BdeSize, PROG_ID *ProgId) 1831 { 1832 MAILBOX *mb = (MAILBOX *)mbq; 1833 1834 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1835 1836 if (ProgId) 1837 mb->mbxCommand = MBX_DOWN_LOAD; 1838 else 1839 mb->mbxCommand = MBX_LOAD_SM; 1840 1841 mb->un.varLdSM.load_cmplt = Complete; 1842 mb->un.varLdSM.method = DL_FROM_SLIM; 1843 mb->un.varLdSM.update_flash = 1; 1844 mb->un.varLdSM.erase_or_prog = Function; 1845 mb->un.varLdSM.dl_to_adr = Base; 1846 mb->un.varLdSM.dl_len = DlByteCount; 1847 1848 if (BdeSize) { 1849 mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET; 1850 } else if (ProgId) { 1851 mb->un.varLdSM.un.prog_id = *ProgId; 1852 } else { 1853 mb->un.varLdSM.un.dl_from_slim_offset = 0; 1854 } 1855 1856 mb->mbxOwner = OWN_HOST; 1857 mbq->mbox_cmpl = NULL; 1858 1859 } /* emlxs_format_prog_flash() */ 1860 1861 1862 static void 1863 emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms) 1864 { 1865 MAILBOX *mb = (MAILBOX *)mbq; 1866 1867 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1868 1869 mb->mbxCommand = MBX_UPDATE_CFG; 1870 mb->un.varUpdateCfg.req_type = UPDATE_DATA; 1871 mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID; 1872 mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS); 1873 mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS); 1874 1875 bcopy((caddr_t)WakeUpParms, 1876 (caddr_t)&(mb->un.varUpdateCfg.cfg_data), 1877 sizeof (WAKE_UP_PARMS)); 1878 mbq->mbox_cmpl = NULL; 1879 1880 } /* emlxs_format_update_parms () */ 1881 1882 1883 /* ARGSUSED */ 1884 static void 1885 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq, 1886 uint32_t region_id, uint32_t size) 1887 { 1888 MAILBOX *mb = (MAILBOX *)mbq; 1889 1890 bzero((void *)mb, MAILBOX_CMD_BSIZE); 1891 1892 mb->mbxCommand = MBX_UPDATE_CFG; 1893 mb->un.varUpdateCfg.Vbit = 1; 1894 mb->un.varUpdateCfg.Obit = 1; 1895 mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET; 1896 mb->un.varUpdateCfg.req_type = UPDATE_DATA; 1897 mb->un.varUpdateCfg.region_id = region_id; 1898 mb->un.varUpdateCfg.entry_len = size; 1899 mb->un.varUpdateCfg.byte_len = size; 1900 mbq->mbox_cmpl = NULL; 1901 1902 } /* emlxs_format_update_pci_cfg() */ 1903 1904 1905 1906 static uint32_t 1907 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1908 PROG_ID * prog_id, uint32_t proc_erom) 1909 { 1910 emlxs_port_t *port = &PPORT; 1911 MAILBOX *mb; 1912 MAILBOXQ *mbox; 1913 uint32_t rval = 0; 1914 1915 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1916 KM_NOSLEEP)) == NULL) { 1917 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1918 "Unable to allocate mailbox buffer."); 1919 1920 return (1); 1921 } 1922 1923 mb = (MAILBOX *)mbox; 1924 1925 if (proc_erom && !(hba->model_info.chip & 1926 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 1927 WakeUpParms->u1.EROM_prog_id = *prog_id; 1928 (void) emlxs_update_exp_rom(hba, WakeUpParms); 1929 } 1930 1931 WakeUpParms->u0.boot_bios_id = *prog_id; 1932 1933 emlxs_format_update_parms(mbox, WakeUpParms); 1934 1935 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 1936 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1937 "Unable to update boot wakeup parms: Mailbox cmd=%x " 1938 "status=%x", mb->mbxCommand, mb->mbxStatus); 1939 1940 rval = 1; 1941 } 1942 1943 if (mbox) { 1944 kmem_free(mbox, sizeof (MAILBOXQ)); 1945 } 1946 1947 return (rval); 1948 1949 } /* emlxs_update_boot_wakeup_parms() */ 1950 1951 1952 1953 static uint32_t 1954 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1955 PROG_ID *prog_id) 1956 { 1957 emlxs_port_t *port = &PPORT; 1958 uint32_t rval = 0; 1959 MAILBOXQ *mbox; 1960 MAILBOX *mb; 1961 1962 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 1963 KM_NOSLEEP)) == NULL) { 1964 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1965 "Unable to allocate mailbox buffer."); 1966 1967 return (1); 1968 } 1969 1970 mb = (MAILBOX *)mbox; 1971 1972 WakeUpParms->prog_id = *prog_id; 1973 1974 emlxs_format_update_parms(mbox, WakeUpParms); 1975 1976 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 1977 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 1978 "Unable to update wakeup parameters: Mailbox cmd=%x " 1979 "status=%x", mb->mbxCommand, mb->mbxStatus); 1980 1981 rval = 1; 1982 } 1983 1984 if (mbox) { 1985 kmem_free(mbox, sizeof (MAILBOXQ)); 1986 } 1987 1988 return (rval); 1989 1990 } /* emlxs_update_ff_wakeup_parms() */ 1991 1992 1993 static uint32_t 1994 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 1995 PROG_ID * prog_id) 1996 { 1997 emlxs_port_t *port = &PPORT; 1998 uint32_t rval = 0; 1999 MAILBOXQ *mbox; 2000 MAILBOX *mb; 2001 2002 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2003 KM_NOSLEEP)) == NULL) { 2004 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2005 "Unable to allocate mailbox buffer."); 2006 2007 return (1); 2008 } 2009 2010 mb = (MAILBOX *)mbox; 2011 2012 WakeUpParms->sli1_prog_id = *prog_id; 2013 2014 emlxs_format_update_parms(mbox, WakeUpParms); 2015 2016 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2017 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2018 "Unable to update wakeup parameters. Mailbox cmd=%x " 2019 "status=%x", mb->mbxCommand, mb->mbxStatus); 2020 2021 rval = 1; 2022 } 2023 2024 if (mbox) { 2025 kmem_free(mbox, sizeof (MAILBOXQ)); 2026 } 2027 2028 return (rval); 2029 2030 } /* emlxs_update_sli1_wakeup_parms() */ 2031 2032 2033 static uint32_t 2034 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 2035 PROG_ID * prog_id) 2036 { 2037 emlxs_port_t *port = &PPORT; 2038 uint32_t rval = 0; 2039 MAILBOXQ *mbox; 2040 MAILBOX *mb; 2041 2042 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2043 KM_NOSLEEP)) == NULL) { 2044 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2045 "Unable to allocate mailbox buffer."); 2046 2047 return (1); 2048 } 2049 2050 mb = (MAILBOX *)mbox; 2051 2052 WakeUpParms->sli2_prog_id = *prog_id; 2053 2054 emlxs_format_update_parms(mbox, WakeUpParms); 2055 2056 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2057 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2058 "Unable to update wakeup parameters. Mailbox cmd=%x " 2059 "status=%x", mb->mbxCommand, mb->mbxStatus); 2060 2061 rval = 1; 2062 } 2063 2064 if (mbox) { 2065 kmem_free(mbox, sizeof (MAILBOXQ)); 2066 } 2067 2068 return (rval); 2069 2070 } /* emlxs_update_sli2_wakeup_parms() */ 2071 2072 2073 static uint32_t 2074 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 2075 PROG_ID *prog_id) 2076 { 2077 emlxs_port_t *port = &PPORT; 2078 uint32_t rval = 0; 2079 MAILBOXQ *mbox; 2080 MAILBOX *mb; 2081 2082 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2083 KM_NOSLEEP)) == NULL) { 2084 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2085 "Unable to allocate mailbox buffer."); 2086 2087 return (1); 2088 } 2089 2090 mb = (MAILBOX *)mbox; 2091 2092 WakeUpParms->sli3_prog_id = *prog_id; 2093 2094 emlxs_format_update_parms(mbox, WakeUpParms); 2095 2096 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2097 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2098 "Unable to update wakeup parameters. Mailbox cmd=%x " 2099 "status=%x", mb->mbxCommand, mb->mbxStatus); 2100 2101 rval = 1; 2102 } 2103 2104 if (mbox) { 2105 kmem_free(mbox, sizeof (MAILBOXQ)); 2106 } 2107 2108 return (rval); 2109 2110 } /* emlxs_update_sli3_wakeup_parms() */ 2111 2112 2113 static uint32_t 2114 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 2115 PROG_ID *prog_id) 2116 { 2117 emlxs_port_t *port = &PPORT; 2118 uint32_t rval = 0; 2119 MAILBOXQ *mbox; 2120 MAILBOX *mb; 2121 2122 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2123 KM_NOSLEEP)) == NULL) { 2124 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2125 "Unable to allocate mailbox buffer."); 2126 2127 return (1); 2128 } 2129 2130 mb = (MAILBOX *)mbox; 2131 2132 WakeUpParms->sli4_prog_id = *prog_id; 2133 2134 emlxs_format_update_parms(mbox, WakeUpParms); 2135 2136 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2137 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2138 "Unable to update wakeup parameters. Mailbox cmd=%x " 2139 "status=%x", mb->mbxCommand, mb->mbxStatus); 2140 2141 rval = 1; 2142 } 2143 2144 if (mbox) { 2145 kmem_free(mbox, sizeof (MAILBOXQ)); 2146 } 2147 2148 return (rval); 2149 2150 } /* emlxs_update_sli4_wakeup_parms() */ 2151 2152 2153 /* ARGSUSED */ 2154 static uint32_t 2155 emlxs_start_rel_download(emlxs_hba_t *hba, 2156 PIMAGE_HDR ImageHdr, 2157 caddr_t Buffer, 2158 PWAKE_UP_PARMS WakeUpParms, 2159 uint32_t MaxRbusSramSize, uint32_t MaxIbusSramSize) 2160 { 2161 emlxs_port_t *port = &PPORT; 2162 MAILBOXQ *mbox; 2163 MAILBOX *mb; 2164 uint32_t *Src; 2165 uint32_t *Dst; 2166 caddr_t DataBuffer = NULL; 2167 uint32_t rval = 1; 2168 uint32_t DlByteCount = ImageHdr->BlockSize; 2169 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 2170 uint32_t DlCount; 2171 uint32_t i; 2172 2173 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2174 "Performing relative download..."); 2175 2176 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 2177 KM_NOSLEEP)) == NULL) { 2178 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2179 "Unable to allocate data buffer."); 2180 2181 return (rval); 2182 } 2183 2184 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2185 KM_NOSLEEP)) == NULL) { 2186 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2187 "Unable to allocate mailbox buffer."); 2188 2189 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 2190 2191 return (rval); 2192 } 2193 2194 if (ImageHdr->Id.Type == FUNC_FIRMWARE) { 2195 switch (MaxRbusSramSize) { 2196 case REDUCED_RBUS_SRAM_CFG: 2197 if (ImageHdr->Id.Id != REDUCED_SRAM_CFG_PROG_ID) { 2198 EMLXS_MSGF(EMLXS_CONTEXT, 2199 &emlxs_image_bad_msg, 2200 "Invalid header id."); 2201 2202 return (1); 2203 } 2204 break; 2205 case FULL_RBUS_SRAM_CFG: 2206 if (ImageHdr->Id.Id != FULL_SRAM_CFG_PROG_ID) { 2207 EMLXS_MSGF(EMLXS_CONTEXT, 2208 &emlxs_image_bad_msg, 2209 "Invalid header id."); 2210 2211 return (1); 2212 } 2213 break; 2214 default: 2215 if (ImageHdr->Id.Id != OTHER_SRAM_CFG_PROG_ID) { 2216 EMLXS_MSGF(EMLXS_CONTEXT, 2217 &emlxs_image_bad_msg, 2218 "Invalid header id."); 2219 2220 return (1); 2221 } 2222 break; 2223 } 2224 } 2225 2226 mb = (MAILBOX *)mbox; 2227 2228 emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0, 2229 &ImageHdr->Id); 2230 2231 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Erasing flash..."); 2232 2233 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2234 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2235 "Unable to erase flash. Mailbox cmd=%x status=%x", 2236 mb->mbxCommand, mb->mbxStatus); 2237 2238 rval = 1; 2239 2240 goto EXIT_REL_DOWNLOAD; 2241 } 2242 2243 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2244 "Programming flash..."); 2245 2246 while (DlByteCount) { 2247 if (DlByteCount > SegSize) { 2248 DlCount = SegSize; 2249 } else { 2250 DlCount = DlByteCount; 2251 } 2252 DlByteCount -= DlCount; 2253 2254 Dst = (uint32_t *)DataBuffer; 2255 Src = (uint32_t *)Buffer; 2256 2257 for (i = 0; i < (DlCount / 4); i++) { 2258 *Dst = *Src; 2259 Dst++; 2260 Src++; 2261 } 2262 2263 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 2264 (volatile uint32_t *) 2265 ((volatile char *)hba->sli.sli3.slim_addr + 2266 sizeof (MAILBOX)), (DlCount / sizeof (uint32_t))); 2267 2268 emlxs_format_prog_flash(mbox, 2269 0, 2270 DlCount, 2271 PROGRAM_FLASH, 2272 (DlByteCount) ? 0 : 1, 0, DlCount, &ImageHdr->Id); 2273 2274 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 2275 MBX_SUCCESS) { 2276 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2277 "Unable to program flash. Mailbox cmd=%x status=%x", 2278 mb->mbxCommand, mb->mbxStatus); 2279 2280 rval = 1; 2281 2282 goto EXIT_REL_DOWNLOAD; 2283 } 2284 2285 Buffer += DlCount; 2286 } 2287 2288 #ifdef FMA_SUPPORT 2289 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 2290 != DDI_FM_OK) { 2291 EMLXS_MSGF(EMLXS_CONTEXT, 2292 &emlxs_invalid_access_handle_msg, NULL); 2293 2294 rval = 1; 2295 2296 goto EXIT_REL_DOWNLOAD; 2297 } 2298 #endif /* FMA_SUPPORT */ 2299 2300 switch (ImageHdr->Id.Type) { 2301 case TEST_PROGRAM: 2302 rval = 0; 2303 break; 2304 2305 case FUNC_FIRMWARE: 2306 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2307 "FF: Updating parms..."); 2308 rval = 2309 emlxs_update_ff_wakeup_parms(hba, WakeUpParms, 2310 &ImageHdr->Id); 2311 break; 2312 2313 case BOOT_BIOS: 2314 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2315 "BOOT: Updating parms..."); 2316 rval = 2317 emlxs_update_boot_wakeup_parms(hba, WakeUpParms, 2318 &ImageHdr->Id, 1); 2319 break; 2320 2321 case SLI1_OVERLAY: 2322 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2323 "SLI1: Updating parms..."); 2324 rval = 2325 emlxs_update_sli1_wakeup_parms(hba, WakeUpParms, 2326 &ImageHdr->Id); 2327 break; 2328 2329 case SLI2_OVERLAY: 2330 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2331 "SLI2: Updating parms..."); 2332 rval = 2333 emlxs_update_sli2_wakeup_parms(hba, WakeUpParms, 2334 &ImageHdr->Id); 2335 break; 2336 2337 case SLI3_OVERLAY: 2338 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2339 "SLI3: Updating parms..."); 2340 rval = 2341 emlxs_update_sli3_wakeup_parms(hba, WakeUpParms, 2342 &ImageHdr->Id); 2343 break; 2344 2345 case SLI4_OVERLAY: 2346 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 2347 "SLI4: Updating parms..."); 2348 rval = 2349 emlxs_update_sli4_wakeup_parms(hba, WakeUpParms, 2350 &ImageHdr->Id); 2351 break; 2352 2353 default: 2354 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 2355 "Image type not supported. Type=%x", ImageHdr->Id.Type); 2356 2357 break; 2358 } 2359 2360 EXIT_REL_DOWNLOAD: 2361 if (DataBuffer) { 2362 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 2363 } 2364 2365 if (mbox) { 2366 kmem_free(mbox, sizeof (MAILBOXQ)); 2367 } 2368 2369 return (rval); 2370 2371 } /* emlxs_start_rel_download() */ 2372 2373 2374 #define FLASH_POLLING_BIT 0x80 2375 #define FLASH_ERROR_BIT 0x20 2376 2377 typedef struct _flash_t 2378 { 2379 uint32_t offset; 2380 uint8_t val; 2381 } flash_t; 2382 2383 2384 2385 static uint32_t 2386 emlxs_write_fcode_flash(emlxs_hba_t *hba, 2387 PIMAGE_HDR ImageHdr, caddr_t Buffer) 2388 { 2389 emlxs_port_t *port = &PPORT; 2390 uint8_t bb; 2391 uint8_t cc; 2392 uint8_t *src; 2393 uint32_t DlByteCount = ImageHdr->BlockSize; 2394 uint32_t i; 2395 uint32_t j; 2396 uint32_t k; 2397 2398 flash_t wr[3] = { 2399 {0x555, 0xaa}, 2400 {0x2aa, 0x55}, 2401 {0x555, 0xa0} 2402 }; 2403 2404 /* Load Fcode */ 2405 src = (uint8_t *)Buffer + sizeof (IMAGE_HDR); 2406 for (i = 0; i < DlByteCount; i++) { 2407 for (k = 0; k < 3; k++) { 2408 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val); 2409 } 2410 2411 /* Reverse Endian word alignment */ 2412 j = (i & 3) ^ 3; 2413 2414 bb = src[j]; 2415 2416 if (j == 0) { 2417 src += 4; 2418 } 2419 2420 SBUS_WRITE_FLASH_COPY(hba, i, bb); 2421 2422 /* check for complete */ 2423 for (;;) { 2424 DELAYUS(20); 2425 2426 cc = SBUS_READ_FLASH_COPY(hba, i); 2427 2428 /* If data matches then continue */ 2429 if (cc == bb) { 2430 break; 2431 } 2432 2433 /* Polling bit will be inverse final value */ 2434 /* while active */ 2435 if ((cc ^ bb) & FLASH_POLLING_BIT) { 2436 /* Still busy */ 2437 2438 /* Check for error bit */ 2439 if (cc & FLASH_ERROR_BIT) { 2440 /* Read data one more time */ 2441 cc = SBUS_READ_FLASH_COPY(hba, i); 2442 2443 /* Check if data matches */ 2444 if (cc == bb) { 2445 break; 2446 } 2447 2448 EMLXS_MSGF(EMLXS_CONTEXT, 2449 &emlxs_download_failed_msg, 2450 "FCode write error: offset:%x " 2451 "wrote:%x read:%x\n", i, bb, cc); 2452 2453 return (1); 2454 } 2455 } 2456 } 2457 } 2458 2459 /* Load Header */ 2460 src = (uint8_t *)ImageHdr; 2461 2462 for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) { 2463 for (k = 0; k < 3; k++) { 2464 SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val); 2465 } 2466 2467 /* Reverse Endian word alignment */ 2468 j = (i & 3) ^ 3; 2469 2470 bb = src[j]; 2471 2472 if (j == 0) { 2473 src += 4; 2474 } 2475 2476 SBUS_WRITE_FLASH_COPY(hba, i, bb); 2477 2478 /* check for complete */ 2479 for (;;) { 2480 DELAYUS(20); 2481 2482 cc = SBUS_READ_FLASH_COPY(hba, i); 2483 2484 /* If data matches then continue */ 2485 if (cc == bb) { 2486 break; 2487 } 2488 2489 /* Polling bit will be inverse final value */ 2490 /* while active */ 2491 if ((cc ^ bb) & FLASH_POLLING_BIT) { 2492 /* Still busy */ 2493 2494 /* Check for error bit */ 2495 if (cc & FLASH_ERROR_BIT) { 2496 /* Read data one more time */ 2497 cc = SBUS_READ_FLASH_COPY(hba, i); 2498 2499 /* Check if data matches */ 2500 if (cc == bb) { 2501 break; 2502 } 2503 2504 EMLXS_MSGF(EMLXS_CONTEXT, 2505 &emlxs_download_failed_msg, 2506 "FCode write error: offset:%x " 2507 "wrote:%x read:%x\n", i, bb, cc); 2508 2509 return (1); 2510 } 2511 } 2512 } 2513 } 2514 2515 #ifdef FMA_SUPPORT 2516 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle) 2517 != DDI_FM_OK) { 2518 EMLXS_MSGF(EMLXS_CONTEXT, 2519 &emlxs_invalid_access_handle_msg, NULL); 2520 return (1); 2521 } 2522 #endif /* FMA_SUPPORT */ 2523 2524 return (0); 2525 2526 } /* emlxs_write_fcode_flash() */ 2527 2528 2529 2530 static uint32_t 2531 emlxs_erase_fcode_flash(emlxs_hba_t *hba) 2532 { 2533 emlxs_port_t *port = &PPORT; 2534 int32_t i, j; 2535 uint8_t cc; 2536 uint32_t offset; 2537 2538 flash_t ef[6] = { 2539 {0x555, 0xaa}, 2540 {0x2aa, 0x55}, 2541 {0x555, 0x80}, 2542 {0x555, 0xaa}, 2543 {0x2aa, 0x55}, 2544 {0x555, 0x10} 2545 }; 2546 2547 /* Auto select */ 2548 flash_t as[3] = { 2549 {0x555, 0xaa}, 2550 {0x2aa, 0x55}, 2551 {0x555, 0x90} 2552 }; 2553 2554 2555 /* Check Manufacturers Code */ 2556 for (i = 0; i < 3; i++) { 2557 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 2558 } 2559 2560 cc = SBUS_READ_FLASH_COPY(hba, 0); 2561 2562 /* Check Device Code */ 2563 for (i = 0; i < 3; i++) { 2564 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 2565 } 2566 2567 cc = SBUS_READ_FLASH_COPY(hba, 1); 2568 2569 2570 /* Check block protections (up to 4 16K blocks = 64K) */ 2571 for (j = 0; j < 4; j++) { 2572 for (i = 0; i < 3; i++) { 2573 SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val); 2574 } 2575 2576 offset = (j << 14) | 0x2; 2577 2578 cc = SBUS_READ_FLASH_COPY(hba, offset); 2579 2580 if (cc == 0x01) { 2581 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 2582 "Block %d is protected and can't be erased.", j); 2583 } 2584 } 2585 2586 /* Write erase flash sequence */ 2587 for (i = 0; i < 6; i++) { 2588 SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val); 2589 } 2590 2591 /* check for complete */ 2592 for (;;) { 2593 /* Delay 3 seconds */ 2594 DELAYMS(3000); 2595 2596 cc = SBUS_READ_FLASH_COPY(hba, 0); 2597 2598 2599 /* If data matches then continue; */ 2600 if (cc == 0xff) { 2601 break; 2602 } 2603 2604 /* Polling bit will be inverse final value while active */ 2605 if ((cc ^ 0xff) & FLASH_POLLING_BIT) { 2606 /* Still busy */ 2607 2608 /* Check for error bit */ 2609 if (cc & FLASH_ERROR_BIT) { 2610 /* Read data one more time */ 2611 cc = SBUS_READ_FLASH_COPY(hba, 0); 2612 2613 /* Check if data matches */ 2614 if (cc == 0xff) { 2615 break; 2616 } 2617 2618 EMLXS_MSGF(EMLXS_CONTEXT, 2619 &emlxs_download_failed_msg, 2620 "FCode write error: offset:%x wrote:%x " 2621 "read:%x\n", i, 0xff, cc); 2622 2623 return (1); 2624 } 2625 } 2626 } 2627 2628 #ifdef FMA_SUPPORT 2629 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle) 2630 != DDI_FM_OK) { 2631 EMLXS_MSGF(EMLXS_CONTEXT, 2632 &emlxs_invalid_access_handle_msg, NULL); 2633 return (1); 2634 } 2635 #endif /* FMA_SUPPORT */ 2636 2637 return (0); 2638 2639 } /* emlxs_erase_fcode_flash() */ 2640 2641 2642 extern uint32_t 2643 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list) 2644 { 2645 emlxs_port_t *port = &PPORT; 2646 LOAD_ENTRY *LoadEntry; 2647 LOAD_LIST *LoadList = NULL; 2648 uint32_t i; 2649 uint32_t rval = 0; 2650 2651 bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY)); 2652 2653 if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST), 2654 KM_NOSLEEP)) == NULL) { 2655 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2656 "Unable to allocate LOADLIST buffer."); 2657 2658 rval = 1; 2659 goto done; 2660 } 2661 2662 if (emlxs_read_load_list(hba, LoadList)) { 2663 rval = 1; 2664 goto done; 2665 } 2666 2667 for (i = 0; i < LoadList->entry_cnt; i++) { 2668 LoadEntry = &LoadList->load_entry[i]; 2669 if ((LoadEntry->un.wd[0] != 0) && 2670 (LoadEntry->un.wd[0] != 0xffffffff)) { 2671 load_list[i] = LoadEntry->un.id; 2672 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2673 "Load List[%d]: %08x %08x", i, 2674 LoadEntry->un.wd[0], LoadEntry->un.wd[1]); 2675 } 2676 } 2677 2678 done: 2679 2680 if (LoadList) { 2681 kmem_free(LoadList, sizeof (LOAD_LIST)); 2682 } 2683 2684 return (rval); 2685 2686 } /* emlxs_get_load_list() */ 2687 2688 2689 extern uint32_t 2690 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms, 2691 uint32_t verbose) 2692 { 2693 emlxs_port_t *port = &PPORT; 2694 MAILBOXQ *mbox; 2695 MAILBOX *mb; 2696 uint32_t rval = 0; 2697 uint32_t *wd; 2698 2699 bzero(WakeUpParms, sizeof (WAKE_UP_PARMS)); 2700 2701 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2702 KM_NOSLEEP)) == NULL) { 2703 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2704 "Unable to allocate mailbox buffer."); 2705 2706 return (1); 2707 } 2708 2709 mb = (MAILBOX *)mbox; 2710 2711 emlxs_format_dump(hba, mbox, 2712 DMP_NV_PARAMS, 2713 WAKE_UP_PARMS_REGION_ID, 2714 sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0); 2715 2716 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2717 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2718 "Unable to get parameters: Mailbox cmd=%x status=%x", 2719 mb->mbxCommand, mb->mbxStatus); 2720 2721 if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) { 2722 rval = (uint32_t)CFG_DATA_NO_REGION; 2723 } else { 2724 rval = 1; 2725 } 2726 } else { 2727 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2728 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 2729 0, hba->sli.sli4.dump_region.size, 2730 DDI_DMA_SYNC_FORKERNEL); 2731 2732 bcopy((caddr_t)hba->sli.sli4.dump_region.virt, 2733 (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS)); 2734 } else { 2735 bcopy((caddr_t)&mb->un.varDmp.resp_offset, 2736 (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS)); 2737 } 2738 2739 if (verbose) { 2740 wd = (uint32_t *)&WakeUpParms->prog_id; 2741 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2742 "Wakeup: prog_id=%08x %08x", wd[0], wd[1]); 2743 2744 wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id; 2745 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2746 "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]); 2747 2748 wd = (uint32_t *)&WakeUpParms->sli1_prog_id; 2749 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2750 "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]); 2751 2752 wd = (uint32_t *)&WakeUpParms->sli2_prog_id; 2753 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2754 "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]); 2755 2756 wd = (uint32_t *)&WakeUpParms->sli3_prog_id; 2757 if (wd[0] || wd[1]) { 2758 EMLXS_MSGF(EMLXS_CONTEXT, 2759 &emlxs_init_debug_msg, 2760 "Wakeup: sli3_prog_id=%08x %08x", wd[0], 2761 wd[1]); 2762 } 2763 2764 wd = (uint32_t *)&WakeUpParms->sli4_prog_id; 2765 if (wd[0] || wd[1]) { 2766 EMLXS_MSGF(EMLXS_CONTEXT, 2767 &emlxs_init_debug_msg, 2768 "Wakeup: sli4_prog_id=%08x %08x", wd[0], 2769 wd[1]); 2770 } 2771 2772 wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id; 2773 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2774 "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]); 2775 2776 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2777 "Wakeup: pci_cfg_rsvd=%x", 2778 WakeUpParms->pci_cfg_rsvd); 2779 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2780 "Wakeup: use_hdw_def=%x", 2781 WakeUpParms->use_hdw_def); 2782 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2783 "Wakeup: pci_cfg_sel=%x", 2784 WakeUpParms->pci_cfg_sel); 2785 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg, 2786 "Wakeup: cfg_lookup=%x", 2787 WakeUpParms->pci_cfg_lookup_sel); 2788 } 2789 } 2790 2791 done: 2792 2793 if (mbox) { 2794 kmem_free(mbox, sizeof (MAILBOXQ)); 2795 } 2796 2797 #ifdef FMA_SUPPORT 2798 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2799 if (emlxs_fm_check_dma_handle(hba, 2800 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { 2801 EMLXS_MSGF(EMLXS_CONTEXT, 2802 &emlxs_invalid_dma_handle_msg, 2803 "emlxs_read_wakeup_parms: hdl=%p", 2804 hba->sli.sli4.dump_region.dma_handle); 2805 rval = 1; 2806 } 2807 } 2808 #endif /* FMA_SUPPORT */ 2809 2810 return (rval); 2811 2812 } /* emlxs_read_wakeup_parms() */ 2813 2814 2815 static uint32_t 2816 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList) 2817 { 2818 emlxs_port_t *port = &PPORT; 2819 LOAD_ENTRY *LoadEntry; 2820 uint32_t *Uptr; 2821 uint32_t CurEntryAddr; 2822 MAILBOXQ *mbox = NULL; 2823 MAILBOX *mb; 2824 2825 bzero((caddr_t)LoadList, sizeof (LOAD_LIST)); 2826 2827 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 2828 KM_NOSLEEP)) == NULL) { 2829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2830 "Unable to allocate mailbox buffer."); 2831 2832 return (1); 2833 } 2834 2835 mb = (MAILBOX *)mbox; 2836 2837 emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR); 2838 2839 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 2840 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2841 "Unable to get load list: Mailbox cmd=%x status=%x", 2842 mb->mbxCommand, mb->mbxStatus); 2843 2844 goto done; 2845 } 2846 2847 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2848 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0, 2849 hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL); 2850 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt; 2851 } else { 2852 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset; 2853 } 2854 2855 LoadList->head = Uptr[0]; 2856 LoadList->tail = Uptr[1]; 2857 2858 CurEntryAddr = LoadList->head; 2859 2860 while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) && 2861 (LoadList->entry_cnt < MAX_LOAD_ENTRY)) { 2862 LoadEntry = &LoadList->load_entry[LoadList->entry_cnt]; 2863 LoadList->entry_cnt++; 2864 2865 emlxs_format_dump(hba, mbox, 2866 DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr); 2867 2868 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 2869 MBX_SUCCESS) { 2870 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 2871 "Unable to get load list (%d): Mailbox cmd=%x " 2872 "status=%x", LoadList->entry_cnt, mb->mbxCommand, 2873 mb->mbxStatus); 2874 2875 goto done; 2876 } 2877 2878 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2879 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 2880 0, hba->sli.sli4.dump_region.size, 2881 DDI_DMA_SYNC_FORKERNEL); 2882 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt; 2883 } else { 2884 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset; 2885 } 2886 2887 LoadEntry->next = Uptr[0]; 2888 LoadEntry->prev = Uptr[1]; 2889 LoadEntry->start_adr = Uptr[2]; 2890 LoadEntry->len = Uptr[3]; 2891 LoadEntry->un.wd[0] = Uptr[4]; 2892 LoadEntry->un.wd[1] = Uptr[5]; 2893 2894 /* update next current load entry address */ 2895 CurEntryAddr = LoadEntry->next; 2896 2897 } /* end of while (not end of list) */ 2898 2899 done: 2900 2901 if (mbox) { 2902 kmem_free(mbox, sizeof (MAILBOXQ)); 2903 } 2904 2905 #ifdef FMA_SUPPORT 2906 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 2907 if (emlxs_fm_check_dma_handle(hba, 2908 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { 2909 EMLXS_MSGF(EMLXS_CONTEXT, 2910 &emlxs_invalid_dma_handle_msg, 2911 "emlxs_read_load_list: hdl=%p", 2912 hba->sli.sli4.dump_region.dma_handle); 2913 return (1); 2914 } 2915 } 2916 #endif /* FMA_SUPPORT */ 2917 2918 return (0); 2919 2920 } /* emlxs_read_load_list() */ 2921 2922 2923 static uint32_t 2924 emlxs_get_abs_image_type(caddr_t Buffer, uint32_t BufferSize) 2925 { 2926 uint32_t Version; 2927 2928 if (BufferSize < (SLI_VERSION_LOC + 4)) 2929 return (0xffffffff); 2930 2931 Buffer += SLI_VERSION_LOC; 2932 Version = *((uint32_t *)Buffer); 2933 2934 return (Version); 2935 2936 } /* emlxs_get_abs_image_type() */ 2937 2938 2939 static uint32_t 2940 emlxs_get_dwc_image_type(emlxs_hba_t *hba, caddr_t Buffer, 2941 uint32_t BufferSize, PAIF_HDR AifHeader) 2942 { 2943 emlxs_port_t *port = &PPORT; 2944 IMAGE_HDR ImageHdr; 2945 uint32_t NextImage; 2946 uint32_t i; 2947 uint8_t *Sptr; 2948 uint8_t *Dptr; 2949 uint32_t HwId = 0xffffffff; 2950 2951 NextImage = SLI_IMAGE_START - AifHeader->ImageBase; 2952 2953 while (BufferSize > NextImage) { 2954 Sptr = (uint8_t *)&Buffer[NextImage]; 2955 Dptr = (uint8_t *)&ImageHdr; 2956 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 2957 Dptr[i] = Sptr[i]; 2958 } 2959 2960 if (ImageHdr.BlockSize == 0xffffffff) 2961 break; 2962 2963 switch (ImageHdr.Id.Type) { 2964 case 6: 2965 case 7: 2966 if (HwId == 0xffffffff) { 2967 HwId = ImageHdr.Id.Id; 2968 } 2969 2970 if (HwId != ImageHdr.Id.Id) { 2971 EMLXS_MSGF(EMLXS_CONTEXT, 2972 &emlxs_image_bad_msg, 2973 "Invalid hardware id. %x %x", HwId, 2974 ImageHdr.Id.Id); 2975 } 2976 break; 2977 } 2978 2979 NextImage += ImageHdr.BlockSize; 2980 } 2981 2982 return (HwId); 2983 2984 } /* emlxs_get_dwc_image_type() */ 2985 2986 2987 static int 2988 emlxs_build_parms(caddr_t Buffer, 2989 PWAKE_UP_PARMS AbsWakeUpParms, 2990 uint32_t BufferSize, PAIF_HDR AifHeader, int32_t DwcFile) 2991 { 2992 IMAGE_HDR ImageHdr; 2993 uint32_t NextImage; 2994 uint32_t i; 2995 int32_t ChangeParams = FALSE; 2996 caddr_t Sptr; 2997 caddr_t Dptr; 2998 2999 bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS)); 3000 3001 if (!DwcFile && ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) { 3002 return (FALSE); 3003 } 3004 3005 NextImage = SLI_IMAGE_START - AifHeader->ImageBase; 3006 3007 while (BufferSize > NextImage) { 3008 Sptr = &Buffer[NextImage]; 3009 Dptr = (caddr_t)&ImageHdr; 3010 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 3011 Dptr[i] = Sptr[i]; 3012 } 3013 3014 if (ImageHdr.BlockSize == 0xffffffff) 3015 break; 3016 3017 switch (ImageHdr.Id.Type) { 3018 case TEST_PROGRAM: 3019 break; 3020 case FUNC_FIRMWARE: 3021 AbsWakeUpParms->prog_id = ImageHdr.Id; 3022 ChangeParams = TRUE; 3023 break; 3024 case BOOT_BIOS: 3025 AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id; 3026 ChangeParams = TRUE; 3027 break; 3028 case SLI1_OVERLAY: 3029 AbsWakeUpParms->sli1_prog_id = ImageHdr.Id; 3030 ChangeParams = TRUE; 3031 break; 3032 case SLI2_OVERLAY: 3033 AbsWakeUpParms->sli2_prog_id = ImageHdr.Id; 3034 ChangeParams = TRUE; 3035 break; 3036 case SLI3_OVERLAY: 3037 AbsWakeUpParms->sli3_prog_id = ImageHdr.Id; 3038 ChangeParams = TRUE; 3039 break; 3040 case SLI4_OVERLAY: 3041 AbsWakeUpParms->sli4_prog_id = ImageHdr.Id; 3042 ChangeParams = TRUE; 3043 break; 3044 default: 3045 break; 3046 } 3047 3048 NextImage += ImageHdr.BlockSize; 3049 } 3050 3051 return (ChangeParams); 3052 3053 } /* emlxs_build_parms() */ 3054 3055 3056 static uint32_t 3057 emlxs_update_wakeup_parms(emlxs_hba_t *hba, 3058 PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms) 3059 { 3060 emlxs_port_t *port = &PPORT; 3061 MAILBOX *mb; 3062 MAILBOXQ *mbox; 3063 uint32_t rval = 0; 3064 3065 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 3066 KM_NOSLEEP)) == NULL) { 3067 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3068 "Unable to allocate mailbox buffer."); 3069 3070 return (1); 3071 } 3072 3073 mb = (MAILBOX *)mbox; 3074 3075 WakeUpParms->prog_id = AbsWakeUpParms->prog_id; 3076 WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id; 3077 WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id; 3078 WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id; 3079 WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id; 3080 WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id; 3081 3082 emlxs_format_update_parms(mbox, WakeUpParms); 3083 3084 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 3085 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3086 "Unable to update wakeup parameters: Mailbox cmd=%x " 3087 "status=%x", mb->mbxCommand, mb->mbxStatus); 3088 3089 rval = 1; 3090 } 3091 3092 if (mbox) { 3093 kmem_free(mbox, sizeof (MAILBOXQ)); 3094 } 3095 3096 return (rval); 3097 3098 } /* emlxs_update_wakeup_parms() */ 3099 3100 3101 static uint32_t 3102 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id, 3103 uint32_t type, char *file_type) 3104 { 3105 emlxs_port_t *port = &PPORT; 3106 3107 /* Create the version label */ 3108 emlxs_decode_version(file->version, file->label); 3109 3110 /* Process the DWC type */ 3111 switch (type) { 3112 case TEST_PROGRAM: 3113 3114 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3115 "%s: TEST: offset=%08x version=%08x, %s", file_type, 3116 file->offset, file->version, file->label); 3117 3118 break; 3119 3120 case BOOT_BIOS: 3121 3122 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3123 "%s: BOOT: offset=%08x version=%08x, %s", file_type, 3124 file->offset, file->version, file->label); 3125 3126 if (!emlxs_bios_check(hba, id)) { 3127 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3128 "BOOT Check: Image not compatible with %s. id=%02x", 3129 hba->model_info.model, id); 3130 3131 return (EMLXS_IMAGE_INCOMPATIBLE); 3132 } 3133 3134 break; 3135 3136 case FUNC_FIRMWARE: /* Stub */ 3137 3138 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3139 "%s: STUB: offset=%08x version=%08x, %s", file_type, 3140 file->offset, file->version, file->label); 3141 3142 if (!emlxs_stub_check(hba, id)) { 3143 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3144 "STUB Check: Image not compatible with %s. id=%02x", 3145 hba->model_info.model, id); 3146 3147 return (EMLXS_IMAGE_INCOMPATIBLE); 3148 } 3149 3150 break; 3151 3152 case SLI1_OVERLAY: 3153 3154 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3155 "%s: SLI1: offset=%08x version=%08x, %s", file_type, 3156 file->offset, file->version, file->label); 3157 3158 if (!emlxs_sli1_check(hba, id)) { 3159 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3160 "SLI1 Check: Image not compatible with %s. id=%02x", 3161 hba->model_info.model, id); 3162 3163 return (EMLXS_IMAGE_INCOMPATIBLE); 3164 } 3165 3166 break; 3167 3168 case SLI2_OVERLAY: 3169 3170 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3171 "%s: SLI2: offset=%08x version=%08x, %s", file_type, 3172 file->offset, file->version, file->label); 3173 3174 if (!emlxs_sli2_check(hba, id)) { 3175 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3176 "SLI2 Check: Image not compatible with %s. id=%02x", 3177 hba->model_info.model, id); 3178 3179 return (EMLXS_IMAGE_INCOMPATIBLE); 3180 } 3181 3182 break; 3183 3184 case SLI3_OVERLAY: 3185 3186 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3187 "%s: SLI3: offset=%08x version=%08x, %s", file_type, 3188 file->offset, file->version, file->label); 3189 3190 if (!emlxs_sli3_check(hba, id)) { 3191 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3192 "SLI3 Check: Image not compatible with %s. id=%02x", 3193 hba->model_info.model, id); 3194 3195 return (EMLXS_IMAGE_INCOMPATIBLE); 3196 } 3197 3198 break; 3199 3200 case SLI4_OVERLAY: 3201 3202 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3203 "%s: SLI4: offset=%08x version=%08x, %s", file_type, 3204 file->offset, file->version, file->label); 3205 3206 if (!emlxs_sli4_check(hba, id)) { 3207 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3208 "SLI4 Check: Image not compatible with %s. id=%02x", 3209 hba->model_info.model, id); 3210 3211 return (EMLXS_IMAGE_INCOMPATIBLE); 3212 } 3213 3214 break; 3215 3216 case SBUS_FCODE: 3217 3218 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3219 "%s: SBUS FCODE: offset=%08x version=%08x, %s", 3220 file_type, file->offset, file->version, file->label); 3221 3222 if (!emlxs_sbus_fcode_check(hba, id)) { 3223 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3224 "SBUS FCODE Check: Image not compatible with %s. " 3225 "id=%02x", hba->model_info.model, id); 3226 3227 return (EMLXS_IMAGE_INCOMPATIBLE); 3228 } 3229 3230 break; 3231 3232 case KERNEL_CODE: 3233 3234 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg, 3235 "%s: KERN: offset=%08x version=%08x, %s", file_type, 3236 file->offset, file->version, file->label); 3237 3238 if (!emlxs_kern_check(hba, id)) { 3239 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg, 3240 "KERN Check: Image not compatible with %s. id=%02x", 3241 hba->model_info.model, id); 3242 3243 return (EMLXS_IMAGE_INCOMPATIBLE); 3244 } 3245 3246 break; 3247 3248 default: 3249 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3250 "%s: Image type not supported. type=%x", file_type, type); 3251 3252 return (EMLXS_IMAGE_BAD); 3253 } 3254 3255 return (0); 3256 3257 } /* emlxs_validate_version() */ 3258 3259 3260 static uint32_t 3261 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size, 3262 emlxs_fw_image_t *image) 3263 { 3264 emlxs_port_t *port = &PPORT; 3265 uint32_t ImageType; 3266 AIF_HDR AifHdr; 3267 IMAGE_HDR ImageHdr; 3268 uint32_t NextImage; 3269 uint32_t FileType; 3270 uint32_t FileLen = 0; 3271 uint32_t TotalLen = 0; 3272 uint32_t *CkSumEnd; 3273 uint32_t id; 3274 uint32_t type; 3275 uint32_t ver; 3276 uint32_t ImageLength; 3277 uint32_t BufferSize; 3278 uint32_t rval = 0; 3279 caddr_t bptr; 3280 emlxs_vpd_t *vpd; 3281 3282 vpd = &VPD; 3283 3284 /* Get image type */ 3285 ImageType = *((uint32_t *)Buffer); 3286 3287 /* Pegasus and beyond adapters */ 3288 if ((ImageType == NOP_IMAGE_TYPE) && 3289 !(hba->model_info.chip & 3290 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 3291 bptr = Buffer; 3292 TotalLen = sizeof (uint32_t); 3293 3294 while (TotalLen < Size) { 3295 if (Size < sizeof (AIF_HDR)) { 3296 EMLXS_MSGF(EMLXS_CONTEXT, 3297 &emlxs_image_bad_msg, 3298 "Invalid image header length: 0x%x < 0x%x", 3299 Size, sizeof (AIF_HDR)); 3300 3301 return (EMLXS_IMAGE_BAD); 3302 } 3303 3304 bcopy(bptr, &AifHdr, sizeof (AIF_HDR)); 3305 emlxs_disp_aif_header(hba, &AifHdr); 3306 3307 ImageLength = AifHdr.RoSize; 3308 3309 /* Validate checksum */ 3310 CkSumEnd = 3311 (uint32_t *)(bptr + ImageLength + 3312 sizeof (AIF_HDR)); 3313 if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) { 3314 EMLXS_MSGF(EMLXS_CONTEXT, 3315 &emlxs_image_bad_msg, 3316 "Invalid checksum found."); 3317 3318 return (EMLXS_IMAGE_BAD); 3319 } 3320 3321 FileType = AifHdr.ZinitBr; 3322 switch (FileType) { 3323 case FILE_TYPE_AWC: 3324 image->awc.offset = 3325 (uint32_t)((uintptr_t)bptr - 3326 (uintptr_t)Buffer); 3327 image->awc.version = AifHdr.AVersion; 3328 image->awc.revcomp = 0; 3329 3330 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 3331 type = emlxs_type_check( 3332 (AifHdr.AVersion & 0xff000000) >> 24); 3333 3334 /* Validate the file version */ 3335 if ((rval = emlxs_validate_version(hba, 3336 &image->awc, id, type, "AWC file"))) { 3337 return (rval); 3338 } 3339 3340 break; 3341 3342 case FILE_TYPE_BWC: 3343 image->bwc.offset = 3344 (uint32_t)((uintptr_t)bptr - 3345 (uintptr_t)Buffer); 3346 image->bwc.version = AifHdr.AVersion; 3347 image->bwc.revcomp = 0; 3348 3349 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 3350 type = emlxs_type_check( 3351 (AifHdr.AVersion & 0xff000000) >> 24); 3352 3353 /* Validate the file version */ 3354 if ((rval = emlxs_validate_version(hba, 3355 &image->bwc, id, type, "BWC file"))) { 3356 return (rval); 3357 } 3358 3359 break; 3360 3361 case FILE_TYPE_DWC: 3362 image->dwc.offset = 3363 (uint32_t)((uintptr_t)bptr - 3364 (uintptr_t)Buffer); 3365 image->dwc.version = AifHdr.AVersion; 3366 image->dwc.revcomp = 0; 3367 3368 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 3369 type = emlxs_type_check( 3370 (AifHdr.AVersion & 0xff000000) >> 24); 3371 3372 /* Validate the file version */ 3373 if ((rval = emlxs_validate_version(hba, 3374 &image->dwc, id, type, "DWC file"))) { 3375 return (rval); 3376 } 3377 3378 /* Scan for program types */ 3379 NextImage = sizeof (AIF_HDR) + 4; 3380 BufferSize = AifHdr.RoSize + AifHdr.RwSize; 3381 3382 while (BufferSize > NextImage) { 3383 bcopy(&bptr[NextImage], &ImageHdr, 3384 sizeof (IMAGE_HDR)); 3385 emlxs_dump_image_header(hba, 3386 &ImageHdr); 3387 3388 /* Validate block size */ 3389 if (ImageHdr.BlockSize == 0xffffffff) { 3390 break; 3391 } 3392 3393 type = emlxs_type_check( 3394 ImageHdr.Id.Type); 3395 3396 /* Calculate the program offset */ 3397 image->prog[type].offset = 3398 (uint32_t)((uintptr_t) 3399 &bptr[NextImage] - 3400 (uintptr_t)Buffer); 3401 3402 /* Acquire the versions */ 3403 image->prog[type].version = 3404 (ImageHdr.Id.Type << 24) | 3405 (ImageHdr.Id.Id << 16) | 3406 (ImageHdr.Id.Ver << 8) | 3407 ImageHdr.Id.Rev; 3408 3409 image->prog[type].revcomp = 3410 ImageHdr.Id.un.revcomp; 3411 3412 /* Validate the file version */ 3413 if ((rval = emlxs_validate_version(hba, 3414 &image->prog[type], ImageHdr.Id.Id, 3415 type, "DWC prog"))) { 3416 return (rval); 3417 } 3418 3419 NextImage += ImageHdr.BlockSize; 3420 3421 } /* while () */ 3422 3423 break; 3424 } 3425 3426 FileLen = 3427 sizeof (AIF_HDR) + ImageLength + 3428 sizeof (uint32_t); 3429 TotalLen += FileLen; 3430 bptr += FileLen; 3431 } 3432 } 3433 3434 /* Pre-pegasus adapters */ 3435 3436 else if (ImageType == NOP_IMAGE_TYPE) { 3437 if (Size < sizeof (AIF_HDR)) { 3438 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3439 "Invalid image header length: 0x%x < 0x%x", Size, 3440 sizeof (AIF_HDR)); 3441 3442 return (EMLXS_IMAGE_BAD); 3443 } 3444 3445 bcopy(Buffer, &AifHdr, sizeof (AIF_HDR)); 3446 emlxs_disp_aif_header(hba, &AifHdr); 3447 3448 ImageLength = AifHdr.RoSize + AifHdr.RwSize; 3449 3450 if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) { 3451 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3452 "Image length incorrect: 0x%x != 0x%x", Size, 3453 sizeof (AIF_HDR) + ImageLength + 3454 sizeof (uint32_t)); 3455 3456 return (EMLXS_IMAGE_BAD); 3457 } 3458 3459 if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) { 3460 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3461 "Invalid imageBase value %x != 0x20000", 3462 AifHdr.ImageBase); 3463 3464 return (EMLXS_IMAGE_BAD); 3465 } 3466 3467 CkSumEnd = 3468 (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR)); 3469 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) { 3470 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3471 "Invalid checksum found."); 3472 3473 return (EMLXS_IMAGE_BAD); 3474 } 3475 3476 image->dwc.offset = 0; 3477 image->dwc.version = AifHdr.AVersion; 3478 image->dwc.revcomp = 0; 3479 3480 id = (AifHdr.AVersion & 0x00ff0000) >> 16; 3481 type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24); 3482 3483 /* Validate the file version */ 3484 if ((rval = emlxs_validate_version(hba, &image->dwc, id, type, 3485 "DWC file"))) { 3486 return (rval); 3487 } 3488 3489 NextImage = SLI_IMAGE_START - AifHdr.ImageBase; 3490 while (Size > NextImage) { 3491 bcopy(&Buffer[NextImage], &ImageHdr, 3492 sizeof (IMAGE_HDR)); 3493 emlxs_dump_image_header(hba, &ImageHdr); 3494 3495 /* Validate block size */ 3496 if (ImageHdr.BlockSize == 0xffffffff) { 3497 break; 3498 } 3499 3500 type = emlxs_type_check(ImageHdr.Id.Type); 3501 3502 /* Calculate the program offset */ 3503 image->prog[type].offset = NextImage; 3504 3505 /* Acquire the versions */ 3506 image->prog[type].version = 3507 (ImageHdr.Id.Type << 24) | 3508 (ImageHdr.Id.Id << 16) | 3509 (ImageHdr.Id.Ver << 8) | 3510 ImageHdr.Id.Rev; 3511 3512 image->prog[type].revcomp = ImageHdr.Id.un.revcomp; 3513 3514 /* Validate the file version */ 3515 if ((rval = emlxs_validate_version(hba, 3516 &image->prog[type], ImageHdr.Id.Id, type, 3517 "DWC prog"))) { 3518 return (rval); 3519 } 3520 3521 NextImage += ImageHdr.BlockSize; 3522 } 3523 } else { 3524 /* Precheck image size */ 3525 if (Size < sizeof (IMAGE_HDR)) { 3526 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3527 "Invalid image header length: 0x%x < 0x%x", Size, 3528 sizeof (IMAGE_HDR)); 3529 3530 return (EMLXS_IMAGE_BAD); 3531 } 3532 3533 bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR)); 3534 emlxs_dump_image_header(hba, &ImageHdr); 3535 3536 /* Validate block size */ 3537 if (ImageHdr.BlockSize == 0xffffffff) { 3538 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3539 "Invalid block size."); 3540 3541 return (EMLXS_IMAGE_BAD); 3542 } 3543 3544 ImageLength = ImageHdr.BlockSize; 3545 3546 /* Validate image length */ 3547 if (Size != ImageLength) { 3548 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3549 "Invalid image length: 0x%x != 0x%x", Size, 3550 ImageLength); 3551 3552 return (EMLXS_IMAGE_BAD); 3553 } 3554 3555 /* Validate Checksum */ 3556 CkSumEnd = 3557 (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) - 3558 1; 3559 if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) { 3560 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 3561 "Invalid checksum found."); 3562 3563 return (EMLXS_IMAGE_BAD); 3564 } 3565 3566 type = emlxs_type_check(ImageHdr.Id.Type); 3567 3568 /* Calculate the program offset */ 3569 image->prog[type].offset = 0; 3570 3571 /* Acquire the versions */ 3572 image->prog[type].version = 3573 (ImageHdr.Id.Type << 24) | (ImageHdr.Id. 3574 Id << 16) | (ImageHdr.Id.Ver << 8) | ImageHdr.Id.Rev; 3575 3576 image->prog[type].revcomp = ImageHdr.Id.un.revcomp; 3577 3578 /* Validate the file version */ 3579 if ((rval = emlxs_validate_version(hba, &image->prog[type], 3580 ImageHdr.Id.Id, type, "DWC file"))) { 3581 return (rval); 3582 } 3583 } 3584 3585 /* 3586 * This checks if a DragonFly (pre-V2 ASIC) SLI2 3587 * image file is greater than version 3.8 3588 */ 3589 if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) { 3590 if (image->prog[SLI2_OVERLAY].version != 0) { 3591 ver = (image->prog[SLI2_OVERLAY].version & 3592 0x0000ff00) >> 8; 3593 3594 if ((((ver & 0xf0) == 0x30) && 3595 ((ver & 0x0f) >= 0x08)) || 3596 ((ver & 0xf0) > 0x30)) { 3597 EMLXS_MSGF(EMLXS_CONTEXT, 3598 &emlxs_image_incompat_msg, 3599 "ASIC Check: Image requires DragonFly " 3600 "V2 ASIC"); 3601 3602 return (EMLXS_IMAGE_INCOMPATIBLE); 3603 } 3604 } 3605 } 3606 3607 return (0); 3608 3609 } /* emlxs_validate_image() */ 3610 3611 3612 static uint32_t 3613 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms) 3614 { 3615 emlxs_port_t *port = &PPORT; 3616 MAILBOXQ *mbox; 3617 MAILBOX *mb; 3618 uint32_t next_address; 3619 uint32_t rval = 0; 3620 3621 if (WakeUpParms->u1.EROM_prog_wd[0] == 0) { 3622 return (1); 3623 } 3624 3625 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 3626 KM_NOSLEEP)) == NULL) { 3627 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3628 "Unable to allocate mailbox buffer."); 3629 3630 return (1); 3631 } 3632 3633 bzero(mbox, sizeof (MAILBOXQ)); 3634 3635 mb = (MAILBOX *)mbox; 3636 mb->mbxCommand = MBX_LOAD_EXP_ROM; 3637 mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE; 3638 mb->un.varLdExpRom.progress = 0; 3639 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 3640 mbox->mbox_cmpl = NULL; 3641 3642 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 3643 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3644 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 3645 mb->mbxCommand, mb->mbxStatus); 3646 3647 rval = 1; 3648 3649 goto SLI_DOWNLOAD_EXIT; 3650 } 3651 3652 if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) { 3653 (void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms); 3654 3655 rval = 1; 3656 goto SLI_DOWNLOAD_EXIT; 3657 } 3658 3659 if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) { 3660 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3661 "Invalid exp ROM progress. progress=%x", 3662 mb->un.varLdExpRom.progress); 3663 3664 rval = 1; 3665 3666 goto SLI_DOWNLOAD_EXIT; 3667 } 3668 3669 /* 3670 * continue Erase 3671 */ 3672 while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) { 3673 3674 next_address = mb->un.varLdExpRom.dl_to_adr; 3675 3676 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3677 3678 mb->mbxCommand = MBX_LOAD_EXP_ROM; 3679 mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE; 3680 mb->un.varLdExpRom.dl_to_adr = next_address; 3681 mb->un.varLdExpRom.progress = 0; 3682 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 3683 mbox->mbox_cmpl = NULL; 3684 3685 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 3686 MBX_SUCCESS) { 3687 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3688 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 3689 mb->mbxCommand, mb->mbxStatus); 3690 3691 rval = 1; 3692 goto SLI_DOWNLOAD_EXIT; 3693 } 3694 3695 } 3696 3697 while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) { 3698 next_address = mb->un.varLdExpRom.dl_to_adr; 3699 3700 bzero((void *)mb, MAILBOX_CMD_BSIZE); 3701 3702 mb->mbxCommand = MBX_LOAD_EXP_ROM; 3703 mb->un.varLdExpRom.step = EROM_CMD_COPY; 3704 mb->un.varLdExpRom.dl_to_adr = next_address; 3705 mb->un.varLdExpRom.progress = 0; 3706 mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id; 3707 mbox->mbox_cmpl = NULL; 3708 3709 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 3710 MBX_SUCCESS) { 3711 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3712 "Unable to load exp ROM. Mailbox cmd=%x status=%x", 3713 mb->mbxCommand, mb->mbxStatus); 3714 3715 rval = 1; 3716 3717 goto SLI_DOWNLOAD_EXIT; 3718 } 3719 } 3720 3721 rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms); 3722 3723 SLI_DOWNLOAD_EXIT: 3724 3725 if (mbox) { 3726 kmem_free(mbox, sizeof (MAILBOXQ)); 3727 } 3728 3729 return (rval); 3730 3731 } /* emlxs_update_exp_rom() */ 3732 3733 3734 /* 3735 * 3736 * FUNCTION NAME: emlxs_start_abs_download_2mb 3737 * 3738 * DESCRIPTION: Perform absolute download for 2 MB flash. A incoming 3739 * buffer may consist of more than 1 file. This function 3740 * will parse the buffer to find all the files. 3741 * 3742 * 3743 * PARAMETERS: 3744 * 3745 * 3746 * RETURNS: 3747 * 3748 */ 3749 /* ARGSUSED */ 3750 static uint32_t 3751 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len, 3752 uint32_t offline, emlxs_fw_image_t *fw_image) 3753 { 3754 emlxs_port_t *port = &PPORT; 3755 caddr_t AwcBuffer = NULL; 3756 caddr_t BwcBuffer = NULL; 3757 caddr_t DwcBuffer = NULL; 3758 AIF_HDR *AwcAifHdr; 3759 AIF_HDR *BwcAifHdr; 3760 AIF_HDR *DwcAifHdr; 3761 uint32_t BWCflag; 3762 emlxs_vpd_t *vpd; 3763 uint32_t i; 3764 uint32_t count; 3765 uint32_t extType = 0; 3766 uint32_t rval = 0; 3767 3768 vpd = &VPD; 3769 3770 /* Check for AWC file */ 3771 if (fw_image->awc.version) { 3772 AwcBuffer = buffer + fw_image->awc.offset; 3773 AwcAifHdr = (AIF_HDR *)AwcBuffer; 3774 } 3775 3776 /* Check for BWC file */ 3777 if (fw_image->bwc.version) { 3778 extType = BWCext; 3779 BwcBuffer = buffer + fw_image->bwc.offset; 3780 BwcAifHdr = (AIF_HDR *)BwcBuffer; 3781 } 3782 3783 /* Check for DWC file */ 3784 if (fw_image->dwc.version) { 3785 extType = DWCext; 3786 DwcBuffer = buffer + fw_image->dwc.offset; 3787 DwcAifHdr = (AIF_HDR *)DwcBuffer; 3788 } 3789 3790 /* Check for program files */ 3791 count = 0; 3792 for (i = 0; i < MAX_PROG_TYPES; i++) { 3793 if (fw_image->prog[i].version) { 3794 count++; 3795 } 3796 } 3797 3798 if (count > 1) { 3799 extType = ALLext; 3800 3801 if (fw_image->bwc.version) { 3802 BWCflag = ALL_WITH_BWC; 3803 } else { 3804 BWCflag = ALL_WITHOUT_BWC; 3805 } 3806 } else { 3807 BWCflag = NO_ALL; 3808 } 3809 3810 /* If nothing to download then quit now */ 3811 if (!AwcBuffer && !DwcBuffer && !BwcBuffer) { 3812 return (0); 3813 } 3814 3815 /* 3816 * Everything checks out, now to just do it 3817 */ 3818 if (offline) { 3819 if (emlxs_offline(hba) != FC_SUCCESS) { 3820 return (EMLXS_OFFLINE_FAILED); 3821 } 3822 3823 if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) { 3824 return (EMLXS_OFFLINE_FAILED); 3825 } 3826 } 3827 3828 if (AwcBuffer) { 3829 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3830 "AWC file: KERN: old=%s new=%s ", vpd->postKernName, 3831 fw_image->awc.label); 3832 3833 rval = emlxs_proc_abs_2mb(hba, 3834 AwcAifHdr, AwcBuffer, FILE_TYPE_AWC, BWCflag, extType); 3835 3836 if (rval) { 3837 goto SLI_DOWNLOAD_2MB_EXIT; 3838 } 3839 } 3840 3841 if (DwcBuffer) { 3842 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3843 "DWC file: TEST: new=%s ", 3844 fw_image->prog[TEST_PROGRAM].label); 3845 3846 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3847 "DWC file: STUB: old=%s new=%s ", vpd->opFwName, 3848 fw_image->prog[FUNC_FIRMWARE].label); 3849 3850 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3851 "DWC file: SLI1: old=%s new=%s ", vpd->sli1FwName, 3852 fw_image->prog[SLI1_OVERLAY].label); 3853 3854 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3855 "DWC file: SLI2: old=%s new=%s ", vpd->sli2FwName, 3856 fw_image->prog[SLI2_OVERLAY].label); 3857 3858 if (vpd->sli3FwRev || fw_image->prog[SLI3_OVERLAY].version) { 3859 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3860 "DWC file: SLI3: old=%s new=%s ", 3861 vpd->sli3FwName, 3862 fw_image->prog[SLI3_OVERLAY].label); 3863 } 3864 3865 if (vpd->sli4FwRev || fw_image->prog[SLI4_OVERLAY].version) { 3866 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3867 "DWC file: SLI4: old=%s new=%s ", 3868 vpd->sli4FwName, 3869 fw_image->prog[SLI4_OVERLAY].label); 3870 } 3871 3872 rval = emlxs_proc_abs_2mb(hba, 3873 DwcAifHdr, DwcBuffer, FILE_TYPE_DWC, BWCflag, extType); 3874 3875 if (rval) { 3876 goto SLI_DOWNLOAD_2MB_EXIT; 3877 } 3878 } 3879 3880 if (BwcBuffer) { 3881 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, 3882 "BWC file: BOOT: old=%s new=%s ", vpd->fcode_version, 3883 fw_image->bwc.label); 3884 3885 rval = emlxs_proc_abs_2mb(hba, 3886 BwcAifHdr, BwcBuffer, FILE_TYPE_BWC, BWCflag, extType); 3887 } 3888 3889 SLI_DOWNLOAD_2MB_EXIT: 3890 3891 if (offline) { 3892 (void) emlxs_online(hba); 3893 } 3894 3895 return (rval); 3896 3897 } /* emlxs_start_abs_download_2mb() */ 3898 3899 3900 /* 3901 * 3902 * FUNCTION NAME: emlxs_proc_abs_2mb 3903 * 3904 * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset 3905 * the port and download the file with sliIssueMbCommand() 3906 * 3907 * 3908 * PARAMETERS: 3909 * 3910 * 3911 * RETURNS: 3912 * 3913 */ 3914 static uint32_t 3915 emlxs_proc_abs_2mb(emlxs_hba_t *hba, 3916 PAIF_HDR AifHdr, 3917 caddr_t EntireBuffer, 3918 uint32_t FileType, uint32_t BWCflag, uint32_t extType) 3919 { 3920 emlxs_port_t *port = &PPORT; 3921 caddr_t Buffer = NULL; 3922 caddr_t DataBuffer = NULL; 3923 uint32_t *Src; 3924 uint32_t *Dst; 3925 MAILBOXQ *mbox; 3926 MAILBOX *mb; 3927 uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize; 3928 uint32_t rval = 0; 3929 uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT; 3930 uint32_t DlToAddr = AifHdr->ImageBase; 3931 uint32_t DlCount; 3932 WAKE_UP_PARMS AbsWakeUpParms; 3933 uint32_t i; 3934 uint32_t NextAddr; 3935 uint32_t EraseByteCount; 3936 uint32_t AreaId; 3937 uint32_t RspProgress = 0; 3938 uint32_t numBootImage = 0; 3939 uint32_t ParamsChg = 0; 3940 uint32_t BufferSize; 3941 3942 if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT, 3943 KM_NOSLEEP)) == NULL) { 3944 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3945 "%x: Unable to allocate data buffer.", FileType); 3946 3947 return (EMLXS_IMAGE_FAILED); 3948 } 3949 3950 bzero(DataBuffer, sizeof (DL_SLIM_SEG_BYTE_COUNT)); 3951 3952 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 3953 KM_NOSLEEP)) == NULL) { 3954 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3955 "%x: Unable to allocate mailbox buffer.", FileType); 3956 3957 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 3958 3959 return (EMLXS_IMAGE_FAILED); 3960 } 3961 3962 mb = (MAILBOX *)mbox; 3963 3964 BufferSize = DlByteCount + sizeof (AIF_HDR) + sizeof (uint32_t); 3965 Buffer = EntireBuffer + sizeof (AIF_HDR); 3966 3967 switch (FileType) { 3968 case FILE_TYPE_AWC: 3969 break; 3970 3971 case FILE_TYPE_BWC: 3972 ParamsChg = emlxs_build_parms_2mb_bwc(hba, 3973 AifHdr, extType, &AbsWakeUpParms); 3974 3975 if (ParamsChg == FALSE) { 3976 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3977 "BWC build parms failed."); 3978 3979 rval = EMLXS_IMAGE_FAILED; 3980 3981 goto EXIT_ABS_DOWNLOAD; 3982 } 3983 break; 3984 3985 case FILE_TYPE_DWC: 3986 ParamsChg = emlxs_build_parms_2mb_dwc(hba, 3987 Buffer, 3988 BufferSize, 3989 AifHdr, &AbsWakeUpParms, BWCflag, extType, &numBootImage); 3990 3991 if (ParamsChg == FALSE) { 3992 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 3993 "DWC build parms failed."); 3994 3995 rval = EMLXS_IMAGE_FAILED; 3996 3997 goto EXIT_ABS_DOWNLOAD; 3998 } 3999 break; 4000 4001 default: 4002 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg, 4003 "Invalid file type: %x", FileType); 4004 4005 rval = EMLXS_IMAGE_BAD; 4006 4007 goto EXIT_ABS_DOWNLOAD; 4008 4009 } 4010 4011 EraseByteCount = AifHdr->Area_Size; 4012 AreaId = AifHdr->Area_ID; 4013 4014 emlxs_format_load_area_cmd(mbox, 4015 DlToAddr, 4016 EraseByteCount, 4017 ERASE_FLASH, 4018 0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE); 4019 4020 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) { 4021 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4022 "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x", 4023 FileType, mb->mbxCommand, mb->mbxStatus); 4024 4025 rval = EMLXS_IMAGE_FAILED; 4026 4027 goto EXIT_ABS_DOWNLOAD; 4028 } 4029 4030 while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) { 4031 NextAddr = mb->un.varLdArea.dl_to_adr; 4032 4033 emlxs_format_load_area_cmd(mbox, 4034 NextAddr, 4035 EraseByteCount, 4036 ERASE_FLASH, 4037 0, 4038 DL_FROM_SLIM_OFFSET, 4039 AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE); 4040 4041 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 4042 MBX_SUCCESS) { 4043 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4044 "%x: Could not erase 2MB Flash2: Mailbox cmd=%x " 4045 "status=%x", FileType, mb->mbxCommand, 4046 mb->mbxStatus); 4047 4048 rval = EMLXS_IMAGE_FAILED; 4049 4050 goto EXIT_ABS_DOWNLOAD; 4051 } 4052 } 4053 4054 while (DlByteCount) { 4055 if (DlByteCount >= SegSize) 4056 DlCount = SegSize; 4057 else 4058 DlCount = DlByteCount; 4059 4060 DlByteCount -= DlCount; 4061 4062 Dst = (uint32_t *)DataBuffer; 4063 Src = (uint32_t *)Buffer; 4064 4065 for (i = 0; i < (DlCount / 4); i++) { 4066 *Dst = *Src; 4067 Dst++; 4068 Src++; 4069 } 4070 4071 WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer, 4072 (volatile uint32_t *)((volatile char *) 4073 hba->sli.sli3.slim_addr + sizeof (MAILBOX)), 4074 (DlCount / sizeof (uint32_t))); 4075 4076 if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) { 4077 emlxs_format_load_area_cmd(mbox, 4078 DlToAddr, 4079 DlCount, 4080 PROGRAM_FLASH, 4081 (DlByteCount) ? 0 : 1, 4082 DL_FROM_SLIM_OFFSET, 4083 AreaId, 4084 MBX_LOAD_AREA, 4085 (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD); 4086 4087 if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != 4088 MBX_SUCCESS) { 4089 EMLXS_MSGF(EMLXS_CONTEXT, 4090 &emlxs_download_failed_msg, 4091 "%x: Could not program 2MB Flash: Mailbox " 4092 "cmd=%x status=%x", FileType, 4093 mb->mbxCommand, mb->mbxStatus); 4094 4095 rval = EMLXS_IMAGE_FAILED; 4096 4097 goto EXIT_ABS_DOWNLOAD; 4098 } 4099 } 4100 4101 RspProgress = mb->un.varLdArea.progress; 4102 4103 Buffer += DlCount; 4104 DlToAddr += DlCount; 4105 } 4106 4107 #ifdef FMA_SUPPORT 4108 if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle) 4109 != DDI_FM_OK) { 4110 EMLXS_MSGF(EMLXS_CONTEXT, 4111 &emlxs_invalid_access_handle_msg, NULL); 4112 4113 rval = EMLXS_IMAGE_FAILED; 4114 4115 goto EXIT_ABS_DOWNLOAD; 4116 } 4117 #endif /* FMA_SUPPORT */ 4118 4119 if (RspProgress != RSP_DOWNLOAD_DONE) { 4120 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4121 "%x: Failed download response received. %x", FileType, 4122 RspProgress); 4123 4124 rval = EMLXS_IMAGE_FAILED; 4125 4126 goto EXIT_ABS_DOWNLOAD; 4127 } 4128 4129 if (ParamsChg) { 4130 if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms, 4131 &AbsWakeUpParms)) { 4132 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4133 "%x: Unable to update parms.", FileType); 4134 4135 rval = EMLXS_IMAGE_FAILED; 4136 } 4137 } 4138 4139 EXIT_ABS_DOWNLOAD: 4140 4141 if (DataBuffer) { 4142 kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT); 4143 } 4144 4145 if (mbox) { 4146 kmem_free(mbox, sizeof (MAILBOXQ)); 4147 } 4148 4149 return (rval); 4150 4151 } /* emlxs_proc_abs_2mb() */ 4152 4153 4154 static void 4155 emlxs_format_load_area_cmd(MAILBOXQ * mbq, 4156 uint32_t Base, 4157 uint32_t DlByteCount, 4158 uint32_t Function, 4159 uint32_t Complete, 4160 uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd) 4161 { 4162 MAILBOX *mb = (MAILBOX *)mbq; 4163 4164 bzero((void *)mb, MAILBOX_CMD_BSIZE); 4165 4166 mb->mbxCommand = MbxCmd; 4167 mb->mbxOwner = OWN_HOST; 4168 mb->un.varLdArea.update_flash = 1; 4169 mb->un.varLdArea.erase_or_prog = Function; 4170 mb->un.varLdArea.dl_to_adr = Base; 4171 mb->un.varLdArea.dl_len = DlByteCount; 4172 mb->un.varLdArea.load_cmplt = Complete; 4173 mb->un.varLdArea.method = DL_FROM_SLIM; 4174 mb->un.varLdArea.area_id = AreaId; 4175 mb->un.varLdArea.step = StepCmd; 4176 mb->un.varLdArea.un.dl_from_slim_offset = DataOffset; 4177 mbq->mbox_cmpl = NULL; 4178 4179 } /* emlxs_format_load_area_cmd() */ 4180 4181 4182 /* ARGSUSED */ 4183 static uint32_t 4184 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, 4185 PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms) 4186 { 4187 emlxs_port_t *port = &PPORT; 4188 uint32_t pId[2]; 4189 uint32_t returnStat; 4190 4191 /* Read wakeup paramters */ 4192 if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) == 4193 CFG_DATA_NO_REGION) { 4194 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4195 "Unable to get BWC parameters."); 4196 return (FALSE); 4197 } 4198 4199 pId[0] = AifHdr->AVersion; 4200 pId[1] = 0; 4201 4202 if (extType == BWCext) { 4203 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0]; 4204 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1]; 4205 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 4206 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 4207 } 4208 4209 else if (extType == ALLext) { 4210 if (!AbsWakeUpParms->u0.boot_bios_wd[0]) { 4211 /* case of EROM inactive */ 4212 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 4213 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 4214 } else { 4215 /* case of EROM active */ 4216 if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) { 4217 /* same ID */ 4218 AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0]; 4219 AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1]; 4220 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 4221 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 4222 } else { 4223 /* different ID */ 4224 AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0]; 4225 AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1]; 4226 4227 returnStat = 4228 emlxs_update_exp_rom(hba, AbsWakeUpParms); 4229 4230 if (returnStat) { 4231 AbsWakeUpParms->u0.boot_bios_wd[0] = 4232 pId[0]; 4233 AbsWakeUpParms->u0.boot_bios_wd[1] = 4234 pId[1]; 4235 } 4236 } 4237 } 4238 } 4239 4240 return (TRUE); 4241 4242 } /* emlxs_build_parms_2mb_bwc() */ 4243 4244 4245 /* ARGSUSED */ 4246 static uint32_t 4247 emlxs_build_parms_2mb_dwc(emlxs_hba_t *hba, 4248 caddr_t Buffer, 4249 uint32_t BufferSize, 4250 PAIF_HDR AifHeader, 4251 PWAKE_UP_PARMS AbsWakeUpParms, 4252 uint32_t BWCflag, uint32_t extType, uint32_t *numBootImage) 4253 { 4254 emlxs_port_t *port = &PPORT; 4255 uint32_t NextImage; 4256 uint32_t i; 4257 IMAGE_HDR ImageHdr; 4258 uint32_t *ptr1; 4259 uint32_t *ptr2; 4260 PROG_ID BootId[MAX_BOOTID]; 4261 uint32_t ChangeParams = FALSE; 4262 WAKE_UP_PARMS WakeUpParms; 4263 caddr_t Sptr; 4264 caddr_t Dptr; 4265 4266 bzero(&BootId, (sizeof (PROG_ID)) * MAX_BOOTID); 4267 4268 /* Read wakeup paramters */ 4269 if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) == 4270 CFG_DATA_NO_REGION) { 4271 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4272 "Unable to get DWC parameters."); 4273 return (FALSE); 4274 } 4275 4276 bcopy((caddr_t)AbsWakeUpParms, (caddr_t)&WakeUpParms, 4277 sizeof (WAKE_UP_PARMS)); 4278 4279 if (((BWCflag == ALL_WITHOUT_BWC) || (extType == DWCext)) && 4280 (WakeUpParms.u0.boot_bios_wd[0])) { 4281 *numBootImage = 0; 4282 } 4283 4284 /* incoming buffer is without aif header */ 4285 NextImage = 0x84 - sizeof (AIF_HDR); 4286 BufferSize -= (sizeof (AIF_HDR) + sizeof (uint32_t)); 4287 4288 while (BufferSize > NextImage) { 4289 Sptr = &Buffer[NextImage]; 4290 Dptr = (caddr_t)&ImageHdr; 4291 for (i = 0; i < sizeof (IMAGE_HDR); i++) { 4292 Dptr[i] = Sptr[i]; 4293 } 4294 4295 if (ImageHdr.BlockSize == 0xffffffff) { 4296 break; 4297 } 4298 4299 switch (ImageHdr.Id.Type) { 4300 case TEST_PROGRAM: 4301 break; 4302 4303 case FUNC_FIRMWARE: 4304 AbsWakeUpParms->prog_id = ImageHdr.Id; 4305 ChangeParams = TRUE; 4306 break; 4307 4308 case BOOT_BIOS: 4309 if (!WakeUpParms.u0.boot_bios_wd[0]) { 4310 if (extType == DWCext) { 4311 break; 4312 } else if (BWCflag == ALL_WITHOUT_BWC) { 4313 /* for possible future changes */ 4314 break; 4315 } 4316 } 4317 ChangeParams = TRUE; 4318 4319 if (*numBootImage < MAX_BOOTID) { 4320 BootId[*numBootImage] = ImageHdr.Id; 4321 (*numBootImage)++; 4322 } 4323 break; 4324 4325 case SLI1_OVERLAY: 4326 AbsWakeUpParms->sli1_prog_id = ImageHdr.Id; 4327 ChangeParams = TRUE; 4328 break; 4329 4330 case SLI2_OVERLAY: 4331 AbsWakeUpParms->sli2_prog_id = ImageHdr.Id; 4332 ChangeParams = TRUE; 4333 break; 4334 4335 case SLI3_OVERLAY: 4336 AbsWakeUpParms->sli3_prog_id = ImageHdr.Id; 4337 ChangeParams = TRUE; 4338 break; 4339 4340 case SLI4_OVERLAY: 4341 AbsWakeUpParms->sli4_prog_id = ImageHdr.Id; 4342 ChangeParams = TRUE; 4343 break; 4344 } 4345 4346 NextImage += ImageHdr.BlockSize; 4347 } 4348 4349 if ((ChangeParams) && ((BWCflag == ALL_WITHOUT_BWC) || 4350 (extType == DWCext))) { 4351 4352 if (*numBootImage > 1) { 4353 for (i = 0; i < *numBootImage; i++) { 4354 ptr1 = 4355 (uint32_t *)&WakeUpParms.u0. 4356 boot_bios_id; 4357 ptr2 = (uint32_t *)&BootId[i]; 4358 4359 if (ptr1[0] == ptr2[0]) { 4360 AbsWakeUpParms->u1.EROM_prog_id = 4361 BootId[i]; 4362 (void) emlxs_update_exp_rom(hba, 4363 AbsWakeUpParms); 4364 break; 4365 } 4366 } 4367 } else { 4368 if (*numBootImage == 1) { 4369 ptr2 = (uint32_t *)&BootId[0]; 4370 4371 if (WakeUpParms.u0.boot_bios_wd[0] == ptr2[0]) { 4372 AbsWakeUpParms->u1.EROM_prog_id = 4373 BootId[0]; 4374 (void) emlxs_update_exp_rom(hba, 4375 AbsWakeUpParms); 4376 } 4377 } 4378 } 4379 } 4380 4381 return (ChangeParams); 4382 4383 4384 } /* emlxs_build_parms_2mb_dwc() */ 4385 4386 4387 extern uint32_t 4388 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize, 4389 uint32_t *MaxIbusSize) 4390 { 4391 emlxs_port_t *port = &PPORT; 4392 MAILBOXQ *mbox; 4393 MAILBOX *mb; 4394 uint32_t *Uptr; 4395 uint32_t rval = 0; 4396 4397 if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), 4398 KM_NOSLEEP)) == NULL) { 4399 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4400 "Unable to allocate mailbox buffer."); 4401 4402 return (1); 4403 } 4404 4405 mb = (MAILBOX *)mbox; 4406 4407 emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR); 4408 4409 if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) != 4410 MBX_SUCCESS) { 4411 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg, 4412 "Unable to get SRAM size: Mailbox cmd=%x status=%x", 4413 mb->mbxCommand, mb->mbxStatus); 4414 4415 rval = 1; 4416 4417 goto Exit_Function; 4418 } 4419 4420 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4421 EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0, 4422 hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL); 4423 Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt; 4424 } else { 4425 Uptr = (uint32_t *)&mb->un.varDmp.resp_offset; 4426 } 4427 4428 *MaxRbusSize = Uptr[0]; 4429 *MaxIbusSize = Uptr[1]; 4430 4431 Exit_Function: 4432 4433 if (mbox) { 4434 kmem_free(mbox, sizeof (MAILBOXQ)); 4435 } 4436 4437 #ifdef FMA_SUPPORT 4438 if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) { 4439 if (emlxs_fm_check_dma_handle(hba, 4440 hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) { 4441 EMLXS_MSGF(EMLXS_CONTEXT, 4442 &emlxs_invalid_dma_handle_msg, 4443 "emlxs_get_max_sram: hdl=%p", 4444 hba->sli.sli4.dump_region.dma_handle); 4445 rval = 1; 4446 } 4447 } 4448 #endif /* FMA_SUPPORT */ 4449 4450 return (rval); 4451 4452 } /* emlxs_get_max_sram() */ 4453 4454 4455 static uint32_t 4456 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version) 4457 { 4458 uint8_t *ptr; 4459 uint8_t ver; 4460 4461 ver = version & 0xff; 4462 ptr = hba->model_info.pt_FF; 4463 4464 while (*ptr) { 4465 if (*ptr++ == ver) { 4466 return (1); 4467 } 4468 } 4469 4470 return (0); 4471 4472 } /* emlxs_kern_check() */ 4473 4474 static uint32_t 4475 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version) 4476 { 4477 uint8_t *ptr; 4478 uint8_t ver; 4479 4480 ver = version & 0xff; 4481 ptr = hba->model_info.pt_2; 4482 4483 while (*ptr) { 4484 if (*ptr++ == ver) { 4485 return (1); 4486 } 4487 } 4488 4489 return (0); 4490 4491 } /* emlxs_stub_check() */ 4492 4493 static uint32_t 4494 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version) 4495 { 4496 uint8_t *ptr; 4497 uint8_t ver; 4498 4499 ver = version & 0xff; 4500 ptr = hba->model_info.pt_3; 4501 4502 while (*ptr) { 4503 if (*ptr++ == ver) { 4504 return (1); 4505 } 4506 } 4507 4508 return (0); 4509 4510 } /* emlxs_bios_check() */ 4511 4512 static uint32_t 4513 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version) 4514 { 4515 uint8_t *ptr; 4516 uint8_t ver; 4517 4518 ver = version & 0xff; 4519 ptr = hba->model_info.pt_6; 4520 4521 while (*ptr) { 4522 if (*ptr++ == ver) { 4523 return (1); 4524 } 4525 } 4526 4527 return (0); 4528 4529 } /* emlxs_sli1_check() */ 4530 4531 static uint32_t 4532 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version) 4533 { 4534 uint8_t *ptr; 4535 uint8_t ver; 4536 4537 ver = version & 0xff; 4538 ptr = hba->model_info.pt_7; 4539 4540 while (*ptr) { 4541 if (*ptr++ == ver) { 4542 return (1); 4543 } 4544 } 4545 4546 return (0); 4547 4548 } /* emlxs_sli2_check() */ 4549 4550 static uint32_t 4551 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version) 4552 { 4553 uint8_t *ptr; 4554 uint8_t ver; 4555 4556 ver = version & 0xff; 4557 ptr = hba->model_info.pt_B; 4558 4559 while (*ptr) { 4560 if (*ptr++ == ver) { 4561 return (1); 4562 } 4563 } 4564 4565 return (0); 4566 4567 } /* emlxs_sli3_check() */ 4568 4569 4570 static uint32_t 4571 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version) 4572 { 4573 uint8_t *ptr; 4574 uint8_t ver; 4575 4576 ver = version & 0xff; 4577 ptr = hba->model_info.pt_E; 4578 4579 while (*ptr) { 4580 if (*ptr++ == ver) { 4581 return (1); 4582 } 4583 } 4584 4585 return (0); 4586 4587 } /* emlxs_sli4_check() */ 4588 4589 4590 static uint32_t 4591 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version) 4592 { 4593 uint8_t *ptr; 4594 uint8_t ver; 4595 4596 ver = version & 0xff; 4597 ptr = hba->model_info.pt_A; 4598 4599 while (*ptr) { 4600 if (*ptr++ == ver) { 4601 return (1); 4602 } 4603 } 4604 4605 return (0); 4606 4607 } /* emlxs_sbus_fcode_check() */ 4608 4609 static uint32_t 4610 emlxs_type_check(uint32_t type) 4611 { 4612 if (type == 0xff) { 4613 return (KERNEL_CODE); 4614 } 4615 4616 if (type >= MAX_PROG_TYPES) { 4617 return (RESERVED_D); 4618 } 4619 4620 return (type); 4621 4622 } /* emlxs_type_check() */ 4623 4624 4625 4626 extern int32_t 4627 emlxs_boot_code_disable(emlxs_hba_t *hba) 4628 { 4629 emlxs_port_t *port = &PPORT; 4630 PROG_ID Id; 4631 emlxs_vpd_t *vpd; 4632 4633 vpd = &VPD; 4634 4635 if (hba->model_info.chip == EMLXS_BE_CHIP) { 4636 return (EMLXS_OP_NOT_SUP); 4637 } 4638 4639 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) { 4640 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4641 "emlxs_boot_code_disable: Unable to read wake up parms."); 4642 4643 return (FC_FAILURE); 4644 } 4645 4646 /* Check if boot code is already disabled */ 4647 if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) { 4648 return (FC_SUCCESS); 4649 } 4650 4651 /* Make sure EROM entry has copy of boot bios entry */ 4652 if (!(hba->model_info.chip & 4653 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) && 4654 (hba->wakeup_parms.u0.boot_bios_wd[0] != 4655 hba->wakeup_parms.u1.EROM_prog_wd[0]) && 4656 (hba->wakeup_parms.u0.boot_bios_wd[1] != 4657 hba->wakeup_parms.u1.EROM_prog_wd[1])) { 4658 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, 4659 &hba->wakeup_parms.u0.boot_bios_id, 1); 4660 } 4661 4662 /* Update the bios id with a zero id */ 4663 /* Don't load the EROM this time */ 4664 bzero(&Id, sizeof (PROG_ID)); 4665 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, &Id, 0); 4666 4667 /* Now read the parms again to verify */ 4668 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 4669 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 4670 vpd->boot_version); 4671 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */ 4672 4673 /* Return the result */ 4674 return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ? 4675 FC_SUCCESS : FC_FAILURE); 4676 4677 } /* emlxs_boot_code_disable() */ 4678 4679 4680 extern int32_t 4681 emlxs_boot_code_enable(emlxs_hba_t *hba) 4682 { 4683 emlxs_port_t *port = &PPORT; 4684 emlxs_vpd_t *vpd; 4685 PROG_ID load_list[MAX_LOAD_ENTRY]; 4686 uint32_t i; 4687 4688 vpd = &VPD; 4689 4690 if (hba->model_info.chip == EMLXS_BE_CHIP) { 4691 return (FC_SUCCESS); 4692 } 4693 4694 /* Read the wakeup parms */ 4695 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) { 4696 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4697 "emlxs_boot_code_enable: Unable to read wake up parms."); 4698 4699 return (FC_FAILURE); 4700 } 4701 4702 /* Check if boot code is already enabled */ 4703 if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) { 4704 return (FC_SUCCESS); 4705 } 4706 4707 if (!(hba->model_info.chip & 4708 (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) { 4709 if (hba->wakeup_parms.u1.EROM_prog_id.Type != BOOT_BIOS) { 4710 return (EMLXS_NO_BOOT_CODE); 4711 } 4712 4713 /* Update the parms with the boot image id */ 4714 /* Don't load the EROM this time */ 4715 (void) emlxs_update_boot_wakeup_parms(hba, &hba->wakeup_parms, 4716 &hba->wakeup_parms.u1.EROM_prog_id, 0); 4717 } else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */ 4718 4719 if (emlxs_get_load_list(hba, load_list)) { 4720 return (FC_FAILURE); 4721 } 4722 4723 /* Scan load list for a boot image */ 4724 for (i = 0; i < MAX_LOAD_ENTRY; i++) { 4725 if (load_list[i].Type == BOOT_BIOS) { 4726 /* Update the parms with the boot image id */ 4727 /* Don't load the EROM this time */ 4728 (void) emlxs_update_boot_wakeup_parms(hba, 4729 &hba->wakeup_parms, &load_list[i], 0); 4730 4731 break; 4732 } 4733 } 4734 4735 if (i == MAX_LOAD_ENTRY) { 4736 return (EMLXS_NO_BOOT_CODE); 4737 } 4738 } 4739 4740 /* Now read the parms again to verify */ 4741 (void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1); 4742 emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0], 4743 vpd->boot_version); 4744 /* (void) strcpy(vpd->fcode_version, vpd->boot_version); */ 4745 4746 /* return the result */ 4747 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ? 4748 FC_SUCCESS : FC_FAILURE); 4749 4750 } /* emlxs_boot_code_enable() */ 4751 4752 4753 4754 extern int32_t 4755 emlxs_boot_code_state(emlxs_hba_t *hba) 4756 { 4757 emlxs_port_t *port = &PPORT; 4758 4759 if (hba->model_info.chip == EMLXS_BE_CHIP) { 4760 return (FC_SUCCESS); 4761 } 4762 4763 /* Read the wakeup parms */ 4764 if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) { 4765 EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg, 4766 "emlxs_boot_code_state: Unable to read wake up parms."); 4767 4768 return (FC_FAILURE); 4769 } 4770 4771 /* return the result */ 4772 return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ? 4773 FC_SUCCESS : FC_FAILURE); 4774 4775 } /* emlxs_boot_code_state() */ 4776