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
9  * http://www.opensource.org/licenses/cddl1.txt.
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 (c) 2004-2012 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <emlxs.h>
28 
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_DOWNLOAD_C);
31 
32 #define	MAX_BOOTID	10
33 
34 static uint32_t	emlxs_erase_fcode_flash(emlxs_hba_t *hba);
35 
36 static uint32_t	emlxs_write_fcode_flash(emlxs_hba_t *hba,
37 			PIMAGE_HDR ImageHdr, caddr_t Buffer);
38 
39 static int32_t	emlxs_build_parms(caddr_t Buffer, PWAKE_UP_PARMS AbsWakeUpParms,
40 			uint32_t BufferSize, PAIF_HDR AifHeader);
41 static uint32_t	emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer,
42 			uint32_t Size, emlxs_fw_image_t *fw_image);
43 static void	emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq,
44 			uint32_t Type, uint32_t RegionId, uint32_t WordCnt,
45 			uint32_t BaseAddr);
46 static uint32_t	emlxs_start_abs_download(emlxs_hba_t *hba, PAIF_HDR AifHdr,
47 			caddr_t Buffer, uint32_t len,
48 			PWAKE_UP_PARMS WakeUpParms);
49 static uint32_t	emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer,
50 			uint32_t len, uint32_t offline,
51 			emlxs_fw_image_t *fw_image);
52 static uint32_t	emlxs_proc_abs_2mb(emlxs_hba_t *hba,
53 			caddr_t EntireBuffer, uint32_t FileType,
54 			uint32_t extType);
55 static void	emlxs_format_load_area_cmd(MAILBOXQ *mbq, uint32_t Base,
56 			uint32_t DlByteCount, uint32_t Function,
57 			uint32_t Complete, uint32_t DataOffset, uint32_t AreaId,
58 			uint8_t MbxCmd, uint32_t StepCmd);
59 static uint32_t	emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba, PAIF_HDR AifHdr,
60 			uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms);
61 static uint32_t	emlxs_update_exp_rom(emlxs_hba_t *hba,
62 			PWAKE_UP_PARMS WakeUpParms);
63 extern uint32_t	emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
64 			uint32_t *MaxIbusSize);
65 static void	emlxs_format_prog_flash(MAILBOXQ *mbq, uint32_t Base,
66 			uint32_t DlByteCount, uint32_t Function,
67 			uint32_t Complete, uint32_t BdeAddress,
68 			uint32_t BdeSize, PROG_ID *ProgId, uint32_t keep);
69 static void	emlxs_format_update_parms(MAILBOXQ *mbq,
70 			PWAKE_UP_PARMS WakeUpParms);
71 static void	emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
72 			uint32_t region_id, uint32_t size);
73 static uint32_t	emlxs_update_wakeup_parms(emlxs_hba_t *hba,
74 			PWAKE_UP_PARMS AbsWakeUpParms,
75 			PWAKE_UP_PARMS WakeUpParms);
76 static uint32_t	emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba,
77 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id,
78 			uint32_t proc_erom);
79 static uint32_t	emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba,
80 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
81 static uint32_t	emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba,
82 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
83 static uint32_t	emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba,
84 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
85 static uint32_t	emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba,
86 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
87 static uint32_t	emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba,
88 			PWAKE_UP_PARMS WakeUpParms, PROG_ID *id);
89 static uint32_t	emlxs_start_rel_download(emlxs_hba_t *hba, PIMAGE_HDR ImageHdr,
90 			caddr_t Buffer, PWAKE_UP_PARMS WakeUpParms,
91 			uint32_t dwc_flag);
92 static uint32_t	emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList);
93 
94 static uint32_t	emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr);
95 
96 static void	emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr);
97 
98 static void	emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image);
99 
100 
101 static uint32_t	emlxs_type_check(uint32_t type);
102 
103 static uint32_t	emlxs_kern_check(emlxs_hba_t *hba, uint32_t version);
104 
105 static uint32_t	emlxs_stub_check(emlxs_hba_t *hba, uint32_t version);
106 
107 static uint32_t	emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version);
108 
109 static uint32_t	emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version);
110 
111 static uint32_t	emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version);
112 
113 static uint32_t	emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version);
114 
115 static uint32_t	emlxs_bios_check(emlxs_hba_t *hba, uint32_t version);
116 
117 static uint32_t	emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version);
118 
119 static uint32_t	emlxs_validate_version(emlxs_hba_t *hba,
120 			emlxs_fw_file_t *file, uint32_t id, uint32_t type,
121 			char *file_type);
122 static uint32_t emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
123 			uint32_t len, emlxs_be_fw_image_t *fw_image);
124 static uint32_t emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
125 			uint32_t len, emlxs_be_fw_image_t *fw_image);
126 
127 
128 static int32_t emlxs_be_verify_phy(emlxs_hba_t *hba, emlxs_be_fw_file_t *file,
129 			MAILBOXQ *mbq, MATCHMAP *mp);
130 static int32_t emlxs_be_verify_crc(emlxs_hba_t *hba,
131 			emlxs_be_fw_file_t *file,
132 			MAILBOXQ *mbq, MATCHMAP *mp);
133 static int32_t emlxs_be_flash_image(emlxs_hba_t *hba, caddr_t buffer,
134 			emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp);
135 static int32_t emlxs_be_fw_download(emlxs_hba_t *hba, caddr_t buffer,
136 			uint32_t len, uint32_t offline);
137 static int32_t emlxs_obj_fw_download(emlxs_hba_t *hba, caddr_t buffer,
138 			uint32_t len, uint32_t offline);
139 static int32_t emlxs_obj_flash_image(emlxs_hba_t *hba, caddr_t buffer,
140 			uint32_t size, MAILBOXQ *mbq, MATCHMAP *mp,
141 			uint32_t *change_status);
142 static uint32_t emlxs_obj_validate_image(emlxs_hba_t *hba, caddr_t buffer,
143 			uint32_t len, emlxs_obj_header_t *obj_hdr);
144 static uint32_t emlxs_be_version(caddr_t buffer, uint32_t size,
145 			uint32_t *plus_flag);
146 static uint32_t emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer,
147 			emlxs_fw_image_t *fw_image);
148 static uint32_t emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId);
149 
150 static void emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *image);
151 
152 static uint32_t emlxs_clean_flash(emlxs_hba_t *hba,
153 			PWAKE_UP_PARMS OldWakeUpParms,
154 			PWAKE_UP_PARMS NewWakeUpParms);
155 
156 /* ************************************************************************* */
157 
158 extern int32_t
emlxs_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)159 emlxs_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
160     uint32_t offline)
161 {
162 	emlxs_port_t *port = &PPORT;
163 	uint32_t *Uptr;
164 	IMAGE_HDR ImageHdr;
165 	AIF_HDR AifHdr;
166 	uint32_t ImageType;
167 	WAKE_UP_PARMS WakeUpParms;
168 	uint32_t rval = 0;
169 	emlxs_fw_image_t fw_image;
170 	uint32_t i;
171 
172 #ifdef EMLXS_LITTLE_ENDIAN
173 	caddr_t local_buffer;
174 	uint32_t *bptr1;
175 	uint32_t *bptr2;
176 #endif /* EMLXS_LITTLE_ENDIAN */
177 
178 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
179 		if (hba->model_info.chip & EMLXS_BE_CHIPS) {
180 			rval = emlxs_be_fw_download(hba, buffer, len, offline);
181 		} else {
182 			rval = emlxs_obj_fw_download(hba, buffer, len, offline);
183 		}
184 		return (rval);
185 	}
186 
187 	if (buffer == NULL || len == 0) {
188 		return (EMLXS_IMAGE_BAD);
189 	}
190 
191 #ifdef EMLXS_LITTLE_ENDIAN
192 	/* We need to swap the image buffer before we start */
193 
194 	/*
195 	 * Use KM_SLEEP to allocate a temporary buffer
196 	 */
197 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
198 
199 	/* Perform a 32 bit swap of the image */
200 	bptr1 = (uint32_t *)local_buffer;
201 	bptr2 = (uint32_t *)buffer;
202 	for (i = 0; i < (len / 4); i++) {
203 		*bptr1 = LE_SWAP32(*bptr2);
204 		bptr1++;
205 		bptr2++;
206 	}
207 
208 	/* Replace the original buffer */
209 	buffer = local_buffer;
210 #endif /* EMLXS_LITTLE_ENDIAN */
211 
212 	bzero(&fw_image, sizeof (emlxs_fw_image_t));
213 	for (i = 0; i < MAX_PROG_TYPES; i++) {
214 		(void) strlcpy(fw_image.prog[i].label, "none",
215 		    sizeof (fw_image.prog[i].label));
216 	}
217 
218 	/* Validate image */
219 	if ((rval = emlxs_validate_image(hba, buffer, len, &fw_image))) {
220 		goto done;
221 	}
222 
223 	/* Verify image */
224 	emlxs_verify_image(hba, &fw_image);
225 
226 	/* Get image type */
227 	Uptr = (uint32_t *)buffer;
228 	ImageType = *Uptr;
229 
230 	/*
231 	 * Pegasus and beyond FW download is done differently
232 	 * for absolute download.
233 	 */
234 
235 	/* Check for absolute image */
236 	if ((ImageType == NOP_IMAGE_TYPE) &&
237 	    !(hba->model_info.chip &
238 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
239 		/*
240 		 * Because 2Mb flash download file format is different from
241 		 * 512k, it needs to be handled differently
242 		 */
243 		if (rval = emlxs_start_abs_download_2mb(hba, buffer, len,
244 		    offline, &fw_image)) {
245 			goto done;
246 		}
247 
248 		/* Offline already handled */
249 		offline = 0;
250 
251 		goto SLI_DOWNLOAD_EXIT;
252 	}
253 
254 	/* Pre-pegasus adapters only */
255 
256 	/* Initialize headers */
257 	if (ImageType == NOP_IMAGE_TYPE) {
258 		bcopy(buffer, &AifHdr, sizeof (AIF_HDR));
259 		bzero((void *)&ImageHdr, sizeof (IMAGE_HDR));
260 	} else { /* PRG file */
261 		bzero((void *)&AifHdr, sizeof (AIF_HDR));
262 		bcopy(buffer, &ImageHdr, sizeof (IMAGE_HDR));
263 	}
264 
265 	/* Everything checks out, now to just do it */
266 
267 	if (offline) {
268 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
269 			offline = 0;
270 
271 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
272 			    "Unable to take adapter offline.");
273 
274 			rval = EMLXS_OFFLINE_FAILED;
275 			goto SLI_DOWNLOAD_EXIT;
276 		}
277 
278 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
279 			offline = 0;
280 
281 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
282 			    "Unable to restart adapter.");
283 
284 			rval = EMLXS_OFFLINE_FAILED;
285 			goto SLI_DOWNLOAD_EXIT;
286 		}
287 	}
288 
289 	/* Pre-pegasus adapters */
290 
291 	if (ImageHdr.Id.Type == SBUS_FCODE) {
292 		/* Erase Flash */
293 		if (emlxs_erase_fcode_flash(hba)) {
294 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
295 			    "Unable to erase flash.");
296 
297 			rval = EMLXS_IMAGE_FAILED;
298 			goto SLI_DOWNLOAD_EXIT;
299 		}
300 
301 		/* Write FCODE */
302 		if (emlxs_write_fcode_flash(hba, &ImageHdr, buffer)) {
303 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
304 			    "Unable to write flash.");
305 
306 			rval = EMLXS_IMAGE_FAILED;
307 			goto SLI_DOWNLOAD_EXIT;
308 		}
309 
310 		goto SLI_DOWNLOAD_EXIT;
311 	}
312 
313 	/* Pre-pegasus PCI adapters */
314 
315 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 1)) {
316 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
317 		    "Unable to get parameters.");
318 
319 		rval = EMLXS_IMAGE_FAILED;
320 
321 		goto SLI_DOWNLOAD_EXIT;
322 	}
323 
324 	if (ImageType == NOP_IMAGE_TYPE) {
325 		if (emlxs_start_abs_download(hba, &AifHdr,
326 		    buffer, len, &WakeUpParms)) {
327 			EMLXS_MSGF(EMLXS_CONTEXT,
328 			    &emlxs_download_failed_msg,
329 			    "Failed to program flash.");
330 
331 			rval = EMLXS_IMAGE_FAILED;
332 
333 			goto SLI_DOWNLOAD_EXIT;
334 		}
335 
336 	} else { /* Relative PRG file */
337 		if (emlxs_start_rel_download(hba, &ImageHdr, buffer,
338 		    &WakeUpParms, 0)) {
339 			EMLXS_MSGF(EMLXS_CONTEXT,
340 			    &emlxs_download_failed_msg,
341 			    "Failed to program flash.");
342 
343 			rval = EMLXS_IMAGE_FAILED;
344 
345 			goto SLI_DOWNLOAD_EXIT;
346 		}
347 	}
348 
349 SLI_DOWNLOAD_EXIT:
350 
351 	if (offline) {
352 		(void) emlxs_online(hba);
353 	}
354 
355 	if (rval == 0) {
356 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
357 		    "Status good.");
358 	}
359 
360 done:
361 
362 #ifdef EMLXS_LITTLE_ENDIAN
363 	/* Free the local buffer */
364 	kmem_free(local_buffer, len);
365 #endif /* EMLXS_LITTLE_ENDIAN */
366 
367 	return (rval);
368 
369 } /* emlxs_fw_download */
370 
371 
372 extern void
emlxs_memset(uint8_t * buffer,uint8_t value,uint32_t size)373 emlxs_memset(uint8_t *buffer, uint8_t value, uint32_t size)
374 {
375 	while (size--) {
376 		*buffer++ = value;
377 	}
378 
379 } /* emlxs_memset () */
380 
381 
382 static int32_t
emlxs_be_flash_image(emlxs_hba_t * hba,caddr_t buffer,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)383 emlxs_be_flash_image(emlxs_hba_t *hba, caddr_t buffer,
384     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
385 {
386 	emlxs_port_t *port = &PPORT;
387 	uint8_t *image_ptr;
388 	uint32_t *wptr;
389 	uint8_t *payload;
390 	MAILBOX4 *mb;
391 	IOCTL_COMMON_FLASHROM *flashrom;
392 	mbox_req_hdr_t	*hdr_req;
393 	uint32_t	image_size;
394 	uint32_t	block_size;
395 	uint32_t	xfer_size;
396 	uint32_t	block_offset;
397 	uint32_t	count;
398 	uint32_t	rval = 0;
399 
400 	if (file->image_size == 0) {
401 		return (0);
402 	}
403 
404 	image_ptr  = (uint8_t *)buffer + file->image_offset;
405 	image_size = file->image_size;
406 	block_size = file->block_size;
407 	block_offset = 0;
408 	mb = (MAILBOX4*)mbq;
409 
410 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
411 	    "%s: Downloading...", file->label);
412 
413 	while (block_size) {
414 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
415 		bzero((void *) mp->virt, mp->size);
416 
417 		xfer_size = min(BE_MAX_XFER_SIZE, block_size);
418 
419 		mb->un.varSLIConfig.be.embedded = 0;
420 		mbq->nonembed = (void *)mp;
421 		mbq->mbox_cmpl = NULL;
422 
423 		mb->mbxCommand = MBX_SLI_CONFIG;
424 		mb->mbxOwner = OWN_HOST;
425 
426 		hdr_req = (mbox_req_hdr_t *)mp->virt;
427 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
428 		hdr_req->opcode = COMMON_OPCODE_WRITE_FLASHROM;
429 		hdr_req->timeout = 0;
430 		hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
431 		    xfer_size;
432 
433 		flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
434 
435 		if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
436 			flashrom->params.opcode = ((block_size == xfer_size)?
437 			    MGMT_PHY_FLASHROM_OPCODE_FLASH:
438 			    MGMT_PHY_FLASHROM_OPCODE_SAVE);
439 			flashrom->params.optype = 0; /* ignored */
440 		} else {
441 			flashrom->params.opcode = ((block_size == xfer_size)?
442 			    MGMT_FLASHROM_OPCODE_FLASH:
443 			    MGMT_FLASHROM_OPCODE_SAVE);
444 			flashrom->params.optype = file->type;
445 		}
446 
447 		flashrom->params.data_buffer_size = xfer_size;
448 		flashrom->params.offset = block_offset;
449 
450 		/* Build data buffer payload */
451 		payload = (uint8_t *)(&flashrom->params.data_buffer);
452 		emlxs_memset(payload, 0xff, xfer_size);
453 
454 		/* Copy remaining image into payload */
455 		if (image_size) {
456 			count = min(image_size, xfer_size);
457 			BE_SWAP32_BCOPY(image_ptr, payload, count);
458 			image_size -= count;
459 			image_ptr  += count;
460 		}
461 
462 		if ((flashrom->params.opcode == MGMT_FLASHROM_OPCODE_FLASH) ||
463 		    (flashrom->params.opcode ==
464 		    MGMT_PHY_FLASHROM_OPCODE_FLASH)) {
465 			wptr = (uint32_t *)&payload[(xfer_size - 12)];
466 
467 			wptr[0] = file->load_address;
468 			wptr[1] = file->image_size;
469 			wptr[2] = 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_be_flash_image() */
493 
494 
495 
496 
497 static int32_t
emlxs_be_verify_crc(emlxs_hba_t * hba,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)498 emlxs_be_verify_crc(emlxs_hba_t *hba,
499     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
500 {
501 	emlxs_port_t *port = &PPORT;
502 	uint32_t *wptr;
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_offset;
509 	uint32_t	rval = 0;
510 	uint32_t	value;
511 
512 	if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
513 		/* PHY Firmware can't be verified */
514 		return (1);
515 	}
516 
517 	xfer_size = 8;
518 	block_offset = file->block_size - xfer_size;
519 	mb = (MAILBOX4*)mbq;
520 
521 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
522 	    "%s: Verifying CRC...", file->label);
523 
524 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
525 	bzero((void *) mp->virt, mp->size);
526 
527 	mb->un.varSLIConfig.be.embedded = 0;
528 	mbq->nonembed = (void *)mp;
529 	mbq->mbox_cmpl = NULL;
530 
531 	mb->mbxCommand = MBX_SLI_CONFIG;
532 	mb->mbxOwner = OWN_HOST;
533 
534 	hdr_req = (mbox_req_hdr_t *)mp->virt;
535 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
536 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
537 	hdr_req->timeout = 0;
538 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
539 	    xfer_size;
540 
541 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
542 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
543 	flashrom->params.optype = file->type;
544 	flashrom->params.data_buffer_size = xfer_size;
545 	flashrom->params.offset = block_offset;
546 
547 	/* Send read request */
548 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
549 	    MBX_SUCCESS) {
550 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
551 		    "%s: Unable to read CRC. status=%x",
552 		    file->label, mb->mbxStatus);
553 
554 		rval = 2;
555 		goto done;
556 	}
557 
558 	payload = (uint8_t *)(&flashrom->params.data_buffer);
559 	wptr = (uint32_t *)(payload + xfer_size - 8);
560 
561 	/* Verify image size */
562 	value = *wptr++;
563 	if (value != file->image_size) {
564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
565 		    "%s: Image size mismatch. %08x != %08x",
566 		    file->label, value, file->image_size);
567 
568 		rval = 1;
569 		goto done;
570 	}
571 
572 	/* Verify block crc */
573 	value = *wptr;
574 	if (value != file->block_crc) {
575 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
576 		    "%s: CRC mismatch. %08x != %08x",
577 		    file->label, value, file->block_crc);
578 		rval = 1;
579 	}
580 
581 done:
582 
583 	if (rval == 0) {
584 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
585 		    "%s: CRC verified.", file->label);
586 	}
587 
588 	return (rval);
589 
590 } /* emlxs_be_verify_crc() */
591 
592 
593 static int32_t
emlxs_be_verify_phy(emlxs_hba_t * hba,emlxs_be_fw_file_t * file,MAILBOXQ * mbq,MATCHMAP * mp)594 emlxs_be_verify_phy(emlxs_hba_t *hba,
595     emlxs_be_fw_file_t *file, MAILBOXQ *mbq, MATCHMAP *mp)
596 {
597 	emlxs_port_t *port = &PPORT;
598 	MAILBOX4 *mb;
599 	IOCTL_COMMON_GET_PHY_DETAILS *phy;
600 	mbox_req_hdr_t	*hdr_req;
601 	uint32_t	rval = 0;
602 
603 	if (file->type != MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
604 		return (1);
605 	}
606 
607 	mb = (MAILBOX4*)mbq;
608 
609 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
610 	    "%s: Getting PHY Details...", file->label);
611 
612 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
613 	bzero((void *) mp->virt, mp->size);
614 
615 	mb->un.varSLIConfig.be.embedded = 0;
616 	mbq->nonembed = (void *)mp;
617 	mbq->mbox_cmpl = NULL;
618 
619 	mb->mbxCommand = MBX_SLI_CONFIG;
620 	mb->mbxOwner = OWN_HOST;
621 
622 	hdr_req = (mbox_req_hdr_t *)mp->virt;
623 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
624 	hdr_req->opcode = COMMON_OPCODE_GET_PHY_DETAILS;
625 	hdr_req->timeout = 0;
626 	hdr_req->req_length = sizeof (IOCTL_COMMON_GET_PHY_DETAILS);
627 
628 	phy = (IOCTL_COMMON_GET_PHY_DETAILS *)(hdr_req + 1);
629 
630 	/* Send read request */
631 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
632 	    MBX_SUCCESS) {
633 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
634 		    "%s: Unable to get PHY details. status=%x",
635 		    file->label, mb->mbxStatus);
636 
637 		rval = 2;
638 		goto done;
639 	}
640 
641 	if ((phy->params.response.phy_type != PHY_TN_8022) ||
642 	    (phy->params.response.interface_type != BASET_10GB_TYPE)) {
643 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
644 		    "%s: PHY not applicable. %08x,%08x",
645 		    file->label,
646 		    phy->params.response.phy_type,
647 		    phy->params.response.interface_type);
648 
649 		rval = 1;
650 	}
651 
652 done:
653 
654 	if (rval == 0) {
655 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
656 		    "%s: PHY verified. %x,%x",
657 		    file->label,
658 		    phy->params.response.phy_type,
659 		    phy->params.response.interface_type);
660 	}
661 
662 	return (rval);
663 
664 } /* emlxs_be_verify_phy() */
665 
666 
667 extern int32_t
emlxs_be_read_fw_version(emlxs_hba_t * hba,emlxs_firmware_t * fw)668 emlxs_be_read_fw_version(emlxs_hba_t *hba, emlxs_firmware_t *fw)
669 {
670 	emlxs_port_t *port = &PPORT;
671 	MAILBOXQ *mbq = NULL;
672 	MATCHMAP *mp = NULL;
673 	MAILBOX4 *mb;
674 	uint32_t *wptr;
675 	uint8_t *payload;
676 	IOCTL_COMMON_FLASHROM *flashrom;
677 	mbox_req_hdr_t	*hdr_req;
678 	uint32_t	xfer_size;
679 	uint32_t	block_offset;
680 	uint32_t	rval = 0;
681 
682 	bzero((void *) fw, sizeof (emlxs_firmware_t));
683 
684 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
685 	    KM_SLEEP)) == NULL) {
686 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
687 		    "read_fw_version: Unable to allocate mailbox buffer.");
688 
689 		rval = 1;
690 		goto done;
691 	}
692 
693 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
694 	    sizeof (IOCTL_COMMON_FLASHROM) + 32))) == NULL) {
695 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
696 		    "read_fw_version: Unable to allocate payload buffer.");
697 
698 		rval = EMLXS_IMAGE_FAILED;
699 		goto done;
700 	}
701 
702 	mb = (MAILBOX4*)mbq;
703 
704 	/* Read CRC and size */
705 	xfer_size = 8;
706 	block_offset = 0x140000 - xfer_size;
707 
708 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
709 	bzero((void *) mp->virt, mp->size);
710 
711 	mb->un.varSLIConfig.be.embedded = 0;
712 	mbq->nonembed = (void *)mp;
713 	mbq->mbox_cmpl = NULL;
714 
715 	mb->mbxCommand = MBX_SLI_CONFIG;
716 	mb->mbxOwner = OWN_HOST;
717 
718 	hdr_req = (mbox_req_hdr_t *)mp->virt;
719 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
720 	hdr_req->opcode = COMMON_OPCODE_READ_FLASHROM;
721 	hdr_req->timeout = 0;
722 	hdr_req->req_length = sizeof (IOCTL_COMMON_FLASHROM) +
723 	    xfer_size;
724 
725 	flashrom = (IOCTL_COMMON_FLASHROM *)(hdr_req + 1);
726 	flashrom->params.opcode = MGMT_FLASHROM_OPCODE_REPORT;
727 	flashrom->params.optype = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
728 	flashrom->params.data_buffer_size = xfer_size;
729 	flashrom->params.offset = block_offset;
730 
731 	/* Send read request */
732 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
733 	    MBX_SUCCESS) {
734 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
735 		    "read_fw_version: Unable to read CRC. status=%x",
736 		    mb->mbxStatus);
737 
738 		rval = 1;
739 		goto done;
740 	}
741 
742 	payload = (uint8_t *)(&flashrom->params.data_buffer);
743 
744 	wptr = (uint32_t *)payload;
745 	fw->size = *wptr++; /* image size */
746 	fw->sli4 = *wptr;   /* block crc */
747 	fw->kern = *wptr;
748 	fw->stub = *wptr;
749 
750 	/* Read version label */
751 	xfer_size = 32;
752 	block_offset = 0x30;
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 = (void *)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 version string. status=%x",
782 		    mb->mbxStatus);
783 
784 		rval = 1;
785 		goto done;
786 	}
787 
788 	payload = (uint8_t *)(&flashrom->params.data_buffer);
789 	BE_SWAP32_BCOPY(payload, (uint8_t *)fw->label, 32);
790 
791 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
792 	    "FCOE FIRMWARE: size=%x version=%s (0x%08x)",
793 	    fw->size, fw->label, fw->sli4);
794 
795 done:
796 
797 	if (mbq) {
798 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
799 	}
800 
801 	if (mp) {
802 		emlxs_mem_buf_free(hba, mp);
803 	}
804 
805 	return (rval);
806 
807 } /* emlxs_be_read_fw_version() */
808 
809 
810 static uint32_t
emlxs_be_version(caddr_t buffer,uint32_t size,uint32_t * plus_flag)811 emlxs_be_version(caddr_t buffer, uint32_t size, uint32_t *plus_flag)
812 {
813 	emlxs_be2_ufi_header_t *ufi_hdr;
814 	char signature[BE2_SIGNATURE_SIZE];
815 	uint32_t be_version = 0;
816 
817 	if (size < sizeof (emlxs_be2_ufi_header_t)) {
818 		return (0);
819 	}
820 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
821 
822 	(void) snprintf(signature, BE2_SIGNATURE_SIZE, "%s+", BE_SIGNATURE);
823 
824 	/* Check if this is a UFI image */
825 	if (strncmp(signature, (char *)ufi_hdr->signature,
826 	    strlen(BE_SIGNATURE)) != 0) {
827 		return (0);
828 	}
829 
830 	/* Check if this is a UFI plus image */
831 	if (plus_flag) {
832 		/* Check if this is a UFI plus image */
833 		if (strncmp(signature, (char *)ufi_hdr->signature,
834 		    strlen(BE_SIGNATURE)+1) == 0) {
835 			*plus_flag = 1;
836 		} else {
837 			*plus_flag = 0;
838 		}
839 	}
840 
841 	if ((ufi_hdr->build[0] >= '1') && (ufi_hdr->build[0] <= '9')) {
842 		be_version = ufi_hdr->build[0] - '0';
843 	}
844 
845 	return (be_version);
846 
847 } /* emlxs_be_version() */
848 
849 
850 static uint32_t
emlxs_be2_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_be_fw_image_t * fw_image)851 emlxs_be2_validate_image(emlxs_hba_t *hba, caddr_t buffer,
852     uint32_t len, emlxs_be_fw_image_t *fw_image)
853 {
854 	emlxs_port_t *port = &PPORT;
855 	emlxs_be2_ufi_header_t *ufi_hdr;
856 	emlxs_be2_flash_dir_t *flash_dir;
857 	emlxs_be2_flash_entry_t *entry;
858 	uint8_t *bptr;
859 	uint32_t *wptr;
860 	uint32_t i;
861 	uint32_t k;
862 	uint32_t mask;
863 	uint32_t value;
864 	uint32_t image_size;
865 	emlxs_be_fw_file_t *file;
866 	emlxs_be_fw_file_t *file2;
867 	uint32_t ufi_plus = 0;
868 	uint32_t be_version = 0;
869 	uint32_t found;
870 
871 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
872 
873 	if (hba->model_info.chip != EMLXS_BE2_CHIP) {
874 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
875 		    "Invalid adapter model.");
876 		return (EMLXS_IMAGE_INCOMPATIBLE);
877 	}
878 
879 	if (len < (sizeof (emlxs_be2_ufi_header_t) +
880 	    sizeof (emlxs_be2_flash_dir_t))) {
881 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
882 		    "Image too small. (%d < %d)",
883 		    len, (sizeof (emlxs_be2_ufi_header_t) +
884 		    sizeof (emlxs_be2_flash_dir_t)));
885 		return (EMLXS_IMAGE_BAD);
886 	}
887 
888 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
889 
890 	/* Check if this is a standard BE2 image */
891 	if (be_version != 2) {
892 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
893 		    "Invalid image provided.");
894 		return (EMLXS_IMAGE_INCOMPATIBLE);
895 	}
896 
897 	ufi_hdr = (emlxs_be2_ufi_header_t *)buffer;
898 
899 #ifdef EMLXS_BIG_ENDIAN
900 	/* Big Endian Swapping */
901 	/* Swap ufi header */
902 	ufi_hdr->checksum =
903 	    SWAP32(ufi_hdr->checksum);
904 	ufi_hdr->antidote =
905 	    SWAP32(ufi_hdr->antidote);
906 	ufi_hdr->controller.vendor_id =
907 	    SWAP32(ufi_hdr->controller.vendor_id);
908 	ufi_hdr->controller.device_id =
909 	    SWAP32(ufi_hdr->controller.device_id);
910 	ufi_hdr->controller.sub_vendor_id =
911 	    SWAP32(ufi_hdr->controller.sub_vendor_id);
912 	ufi_hdr->controller.sub_device_id =
913 	    SWAP32(ufi_hdr->controller.sub_device_id);
914 	ufi_hdr->file_length =
915 	    SWAP32(ufi_hdr->file_length);
916 	ufi_hdr->chunk_num =
917 	    SWAP32(ufi_hdr->chunk_num);
918 	ufi_hdr->chunk_cnt =
919 	    SWAP32(ufi_hdr->chunk_cnt);
920 	ufi_hdr->image_cnt =
921 	    SWAP32(ufi_hdr->image_cnt);
922 #endif /* EMLXS_BIG_ENDIAN */
923 
924 	if (len != ufi_hdr->file_length) {
925 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
926 		    "Invalid image size (%d != %d)",
927 		    len, ufi_hdr->file_length);
928 
929 		return (EMLXS_IMAGE_BAD);
930 	}
931 
932 	/* Scan for flash dir signature */
933 	bptr = (uint8_t *)buffer;
934 	flash_dir = NULL;
935 	for (i = 0; i < len; i++, bptr++) {
936 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
937 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
938 			flash_dir = (emlxs_be2_flash_dir_t *)bptr;
939 			break;
940 		}
941 	}
942 
943 	if (!flash_dir) {
944 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
945 		    "Unable to find flash directory.");
946 
947 		return (EMLXS_IMAGE_BAD);
948 	}
949 
950 #ifdef EMLXS_BIG_ENDIAN
951 	/* Big Endian Swapping */
952 	/* Swap flash dir */
953 	flash_dir->header.format_rev =
954 	    SWAP32(flash_dir->header.format_rev);
955 	flash_dir->header.checksum =
956 	    SWAP32(flash_dir->header.checksum);
957 	flash_dir->header.antidote =
958 	    SWAP32(flash_dir->header.antidote);
959 	flash_dir->header.build_num =
960 	    SWAP32(flash_dir->header.build_num);
961 	flash_dir->header.active_entry_mask =
962 	    SWAP32(flash_dir->header.active_entry_mask);
963 	flash_dir->header.valid_entry_mask =
964 	    SWAP32(flash_dir->header.valid_entry_mask);
965 	flash_dir->header.orig_content_mask =
966 	    SWAP32(flash_dir->header.orig_content_mask);
967 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
968 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
969 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
970 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
971 	flash_dir->header.resv4 = SWAP32(flash_dir->header.resv4);
972 
973 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
974 		flash_dir->header.controller[i].vendor_id =
975 		    SWAP32(flash_dir->header.controller[i].vendor_id);
976 		flash_dir->header.controller[i].device_id =
977 		    SWAP32(flash_dir->header.controller[i].device_id);
978 		flash_dir->header.controller[i].sub_vendor_id =
979 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
980 		flash_dir->header.controller[i].sub_device_id =
981 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
982 	}
983 
984 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++,  mask <<= 1) {
985 
986 		if (!(flash_dir->header.valid_entry_mask & mask)) {
987 			continue;
988 		}
989 
990 		entry = &flash_dir->entry[i];
991 
992 		if ((entry->type == 0) ||
993 		    (entry->type == (uint32_t)-1) ||
994 		    (entry->image_size == 0)) {
995 			continue;
996 		}
997 
998 		flash_dir->entry[i].type =
999 		    SWAP32(flash_dir->entry[i].type);
1000 		flash_dir->entry[i].offset =
1001 		    SWAP32(flash_dir->entry[i].offset);
1002 		flash_dir->entry[i].pad_size =
1003 		    SWAP32(flash_dir->entry[i].pad_size);
1004 		flash_dir->entry[i].image_size =
1005 		    SWAP32(flash_dir->entry[i].image_size);
1006 		flash_dir->entry[i].checksum =
1007 		    SWAP32(flash_dir->entry[i].checksum);
1008 		flash_dir->entry[i].entry_point =
1009 		    SWAP32(flash_dir->entry[i].entry_point);
1010 		flash_dir->entry[i].resv0 =
1011 		    SWAP32(flash_dir->entry[i].resv0);
1012 		flash_dir->entry[i].resv1 =
1013 		    SWAP32(flash_dir->entry[i].resv1);
1014 	}
1015 #endif /* EMLXS_BIG_ENDIAN */
1016 
1017 	/* Verify adapter model */
1018 	found = 0;
1019 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1020 		if (flash_dir->header.controller[i].device_id ==
1021 		    hba->model_info.device_id) {
1022 			found = 1;
1023 		}
1024 	}
1025 
1026 	if (!found) {
1027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1028 		    "Invalid adapter device id=0x%x.",
1029 		    hba->model_info.device_id);
1030 		return (EMLXS_IMAGE_INCOMPATIBLE);
1031 	}
1032 
1033 	/* Build fw_image table */
1034 	fw_image->be_version = 2;
1035 	fw_image->ufi_plus = ufi_plus;
1036 	for (i = 0, mask = 1; i < BE_FLASH_ENTRIES; i++, mask <<= 1) {
1037 
1038 		if (!(flash_dir->header.valid_entry_mask & mask)) {
1039 			continue;
1040 		}
1041 
1042 		entry = &flash_dir->entry[i];
1043 
1044 		if ((entry->type == 0) ||
1045 		    (entry->type == (uint32_t)-1) ||
1046 		    (entry->image_size == 0)) {
1047 			continue;
1048 		}
1049 
1050 		switch (entry->type) {
1051 		case BE_FLASHTYPE_REDBOOT:
1052 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1053 			(void) strlcpy(file->label, "REDBOOT",
1054 			    sizeof (file->label));
1055 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1056 			break;
1057 		case BE_FLASHTYPE_ISCSI_BIOS:
1058 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1059 			(void) strlcpy(file->label, "ISCSI BIOS",
1060 			    sizeof (file->label));
1061 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1062 			break;
1063 		case BE_FLASHTYPE_PXE_BIOS:
1064 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1065 			(void) strlcpy(file->label, "PXE BIOS",
1066 			    sizeof (file->label));
1067 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1068 			break;
1069 		case BE_FLASHTYPE_FCOE_BIOS:
1070 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1071 			(void) strlcpy(file->label, "FCOE BIOS",
1072 			    sizeof (file->label));
1073 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1074 			break;
1075 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1076 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1077 			(void) strlcpy(file->label, "ISCSI FIRMWARE",
1078 			    sizeof (file->label));
1079 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1080 			break;
1081 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1082 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1083 			(void) strlcpy(file->label, "FCOE FIRMWARE",
1084 			    sizeof (file->label));
1085 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1086 			break;
1087 		case BE_FLASHTYPE_FCOE_BACKUP:
1088 		case BE_FLASHTYPE_ISCSI_BACKUP:
1089 			continue;
1090 
1091 		default:
1092 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1093 			    "Unknown image type found.  type=%x",
1094 			    entry->type);
1095 			continue;
1096 		}
1097 
1098 		file->be_version = fw_image->be_version;
1099 		file->ufi_plus = fw_image->ufi_plus;
1100 		file->image_size = entry->image_size;
1101 		image_size = BE_SWAP32(entry->image_size);
1102 
1103 		if (ufi_plus) {
1104 			file->image_offset = entry->offset;
1105 			file->block_size   = entry->pad_size;
1106 			file->block_crc    = entry->checksum;
1107 			file->load_address = entry->entry_point;
1108 
1109 		} else {
1110 			file->image_offset = entry->offset +
1111 			    sizeof (emlxs_be2_ufi_header_t);
1112 
1113 			/* Get entry block size and crc */
1114 			k = file->image_offset + file->image_size;
1115 			k &= 0xFFFFFFFC;
1116 
1117 			wptr = (uint32_t *)(buffer +  k);
1118 			for (; k < len; k += 4) {
1119 				if (*wptr++ == image_size) {
1120 					/* Calculate block_size */
1121 					file->block_size = (k + 8) -
1122 					    file->image_offset;
1123 
1124 					/* Read load_address */
1125 					value = *(wptr - 2);
1126 					file->load_address = BE_SWAP32(value);
1127 
1128 					/* Read block_crc */
1129 					value = *wptr;
1130 					file->block_crc = BE_SWAP32(value);
1131 
1132 					break;
1133 				}
1134 			}
1135 
1136 			if (k >= len) {
1137 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1138 				    "%s: End of block not found. offset=%x",
1139 				    file->label, file->image_offset);
1140 
1141 				bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1142 				return (EMLXS_IMAGE_BAD);
1143 			}
1144 		}
1145 
1146 		/* Make sure image will fit in block specified */
1147 		if (file->image_size + 12 > file->block_size) {
1148 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1149 			    "%s: Image too large for block. image=%x block=%x",
1150 			    file->label, file->image_size, file->block_size);
1151 
1152 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1153 			return (EMLXS_IMAGE_BAD);
1154 		}
1155 
1156 		/* Automatically create a backup file entry for firmware */
1157 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1158 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1159 
1160 			bcopy((uint8_t *)file, (uint8_t *)file2,
1161 			    sizeof (emlxs_be_fw_file_t));
1162 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1163 			(void) strlcpy(file2->label, "FCOE BACKUP",
1164 			    sizeof (file2->label));
1165 
1166 			/* Save FCOE version info */
1167 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1168 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1169 			    BE_VERSION_SIZE);
1170 			fw_image->fcoe_version = file->block_crc;
1171 
1172 		} else if (file->type ==
1173 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1174 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1175 
1176 			bcopy((uint8_t *)file, (uint8_t *)file2,
1177 			    sizeof (emlxs_be_fw_file_t));
1178 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1179 			(void) strlcpy(file2->label, "ISCSI BACKUP",
1180 			    sizeof (file2->label));
1181 
1182 			/* Save ISCSI version info */
1183 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1184 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1185 			    BE_VERSION_SIZE);
1186 			fw_image->iscsi_version = file->block_crc;
1187 		}
1188 	}
1189 
1190 	if (fw_image->fcoe_version == 0) {
1191 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1192 		    "Unable to find FCOE firmware component.");
1193 
1194 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1195 		return (EMLXS_IMAGE_BAD);
1196 	}
1197 
1198 	/* Display contents */
1199 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1200 	    "BE2 UFI Image: %08x, %s", fw_image->fcoe_version,
1201 	    fw_image->fcoe_label);
1202 
1203 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1204 		file = &fw_image->file[i];
1205 
1206 		if (file->image_size == 0) {
1207 			continue;
1208 		}
1209 
1210 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1211 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1212 		    "load=%x",
1213 		    file->label, file->be_version, (file->ufi_plus)?"+":"",
1214 		    file->type, file->block_size, file->image_size,
1215 		    file->image_offset, file->block_crc, file->load_address);
1216 	}
1217 
1218 	return (0);
1219 
1220 } /* emlxs_be2_validate_image() */
1221 
1222 
1223 static uint32_t
emlxs_be3_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_be_fw_image_t * fw_image)1224 emlxs_be3_validate_image(emlxs_hba_t *hba, caddr_t buffer,
1225     uint32_t len, emlxs_be_fw_image_t *fw_image)
1226 {
1227 	emlxs_port_t *port = &PPORT;
1228 	emlxs_be3_ufi_header_t *ufi_hdr;
1229 	emlxs_be3_flash_dir_t *flash_dir;
1230 	emlxs_be3_flash_entry_t *entry;
1231 	emlxs_be3_image_header_t *flash_image_hdr;
1232 	emlxs_be3_image_header_t *image_hdr;
1233 	uint8_t *bptr;
1234 	uint32_t *wptr;
1235 	uint32_t i;
1236 	uint32_t value;
1237 	emlxs_be_fw_file_t *file;
1238 	emlxs_be_fw_file_t *file2;
1239 	uint32_t ufi_plus = 0;
1240 	uint32_t be_version = 0;
1241 	uint32_t found;
1242 
1243 	bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1244 
1245 	if (hba->model_info.chip != EMLXS_BE3_CHIP) {
1246 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1247 		    "Invalid adapter model.");
1248 		return (EMLXS_IMAGE_INCOMPATIBLE);
1249 	}
1250 
1251 	if (len < (sizeof (emlxs_be3_ufi_header_t) +
1252 	    sizeof (emlxs_be3_flash_dir_t))) {
1253 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1254 		    "Image too small. (%d < %d)",
1255 		    len, (sizeof (emlxs_be3_ufi_header_t) +
1256 		    sizeof (emlxs_be3_flash_dir_t)));
1257 		return (EMLXS_IMAGE_BAD);
1258 	}
1259 
1260 	be_version = emlxs_be_version(buffer, len, &ufi_plus);
1261 
1262 	/* Check if this is a standard BE3 image */
1263 	if (be_version != 3) {
1264 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1265 		    "Invalid image provided.");
1266 		return (EMLXS_IMAGE_INCOMPATIBLE);
1267 	}
1268 
1269 	ufi_hdr = (emlxs_be3_ufi_header_t *)buffer;
1270 
1271 #ifdef EMLXS_BIG_ENDIAN
1272 	/* Big Endian Swapping */
1273 	/* Swap ufi header */
1274 	ufi_hdr->ufi_version =
1275 	    SWAP32(ufi_hdr->ufi_version);
1276 	ufi_hdr->file_length =
1277 	    SWAP32(ufi_hdr->file_length);
1278 	ufi_hdr->checksum =
1279 	    SWAP32(ufi_hdr->checksum);
1280 	ufi_hdr->antidote =
1281 	    SWAP32(ufi_hdr->antidote);
1282 	ufi_hdr->image_cnt =
1283 	    SWAP32(ufi_hdr->image_cnt);
1284 #endif /* EMLXS_BIG_ENDIAN */
1285 
1286 	if (len != ufi_hdr->file_length) {
1287 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1288 		    "Invalid image size (%d != %d)",
1289 		    len, ufi_hdr->file_length);
1290 
1291 		return (EMLXS_IMAGE_BAD);
1292 	}
1293 
1294 	flash_image_hdr = NULL;
1295 	image_hdr = (emlxs_be3_image_header_t *)(buffer +
1296 	    sizeof (emlxs_be3_ufi_header_t));
1297 	for (i = 0; i < ufi_hdr->image_cnt; i++, image_hdr++) {
1298 #ifdef EMLXS_BIG_ENDIAN
1299 		image_hdr->id = SWAP32(image_hdr->id);
1300 		image_hdr->offset = SWAP32(image_hdr->offset);
1301 		image_hdr->length = SWAP32(image_hdr->length);
1302 		image_hdr->checksum = SWAP32(image_hdr->checksum);
1303 #endif /* EMLXS_BIG_ENDIAN */
1304 
1305 		if (image_hdr->id == UFI_BE3_FLASH_ID) {
1306 			flash_image_hdr = image_hdr;
1307 		}
1308 	}
1309 
1310 	if (!flash_image_hdr) {
1311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1312 		    "No flash image found.");
1313 
1314 		return (EMLXS_IMAGE_BAD);
1315 	}
1316 
1317 	/* Scan for flash dir signature */
1318 	bptr = (uint8_t *)buffer + flash_image_hdr->offset;
1319 	flash_dir = NULL;
1320 	for (i = 0; i < flash_image_hdr->length; i++, bptr++) {
1321 		if (strncmp((char *)bptr, BE_DIR_SIGNATURE,
1322 		    sizeof (BE_DIR_SIGNATURE)) == 0) {
1323 			flash_dir = (emlxs_be3_flash_dir_t *)bptr;
1324 			break;
1325 		}
1326 	}
1327 
1328 	if (!flash_dir) {
1329 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1330 		    "Unable to find flash directory.");
1331 
1332 		return (EMLXS_IMAGE_BAD);
1333 	}
1334 
1335 #ifdef EMLXS_BIG_ENDIAN
1336 	/* Big Endian Swapping */
1337 	/* Swap flash dir */
1338 	flash_dir->header.format_rev =
1339 	    SWAP32(flash_dir->header.format_rev);
1340 	flash_dir->header.checksum =
1341 	    SWAP32(flash_dir->header.checksum);
1342 	flash_dir->header.antidote =
1343 	    SWAP32(flash_dir->header.antidote);
1344 	flash_dir->header.entry_count =
1345 	    SWAP32(flash_dir->header.entry_count);
1346 	flash_dir->header.resv0 = SWAP32(flash_dir->header.resv0);
1347 	flash_dir->header.resv1 = SWAP32(flash_dir->header.resv1);
1348 	flash_dir->header.resv2 = SWAP32(flash_dir->header.resv2);
1349 	flash_dir->header.resv3 = SWAP32(flash_dir->header.resv3);
1350 
1351 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1352 		flash_dir->header.controller[i].vendor_id =
1353 		    SWAP32(flash_dir->header.controller[i].vendor_id);
1354 		flash_dir->header.controller[i].device_id =
1355 		    SWAP32(flash_dir->header.controller[i].device_id);
1356 		flash_dir->header.controller[i].sub_vendor_id =
1357 		    SWAP32(flash_dir->header.controller[i].sub_vendor_id);
1358 		flash_dir->header.controller[i].sub_device_id =
1359 		    SWAP32(flash_dir->header.controller[i].sub_device_id);
1360 	}
1361 
1362 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1363 		entry = &flash_dir->entry[i];
1364 
1365 		if ((entry->type == 0) ||
1366 		    (entry->type == (uint32_t)-1) ||
1367 		    (entry->image_size == 0)) {
1368 			continue;
1369 		}
1370 
1371 		flash_dir->entry[i].type =
1372 		    SWAP32(flash_dir->entry[i].type);
1373 		flash_dir->entry[i].offset =
1374 		    SWAP32(flash_dir->entry[i].offset);
1375 		flash_dir->entry[i].block_size =
1376 		    SWAP32(flash_dir->entry[i].block_size);
1377 		flash_dir->entry[i].image_size =
1378 		    SWAP32(flash_dir->entry[i].image_size);
1379 		flash_dir->entry[i].checksum =
1380 		    SWAP32(flash_dir->entry[i].checksum);
1381 		flash_dir->entry[i].entry_point =
1382 		    SWAP32(flash_dir->entry[i].entry_point);
1383 		flash_dir->entry[i].resv0 =
1384 		    SWAP32(flash_dir->entry[i].resv0);
1385 		flash_dir->entry[i].resv1 =
1386 		    SWAP32(flash_dir->entry[i].resv1);
1387 	}
1388 #endif /* EMLXS_BIG_ENDIAN */
1389 
1390 	/* Verify image checksum */
1391 	if (flash_dir->header.checksum != flash_image_hdr->checksum) {
1392 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1393 		    "Invalid flash directory checksum. (%x != %x)\n",
1394 		    flash_dir->header.checksum, flash_image_hdr->checksum);
1395 		return (EMLXS_IMAGE_BAD);
1396 	}
1397 
1398 	/* Verify adapter model */
1399 	found = 0;
1400 	for (i = 0; i < BE_CONTROLLER_SIZE; i++) {
1401 		if (flash_dir->header.controller[i].device_id ==
1402 		    hba->model_info.device_id) {
1403 			found = 1;
1404 		}
1405 	}
1406 
1407 	if (!found) {
1408 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1409 		    "Invalid adapter device id=0x%x.",
1410 		    hba->model_info.device_id);
1411 		return (EMLXS_IMAGE_INCOMPATIBLE);
1412 	}
1413 
1414 	/* Build fw_image table */
1415 	fw_image->be_version = 3;
1416 	fw_image->ufi_plus = ufi_plus;
1417 	for (i = 0; i < flash_dir->header.entry_count; i++) {
1418 		entry = &flash_dir->entry[i];
1419 
1420 		if ((entry->type == 0) ||
1421 		    (entry->type == (uint32_t)-1) ||
1422 		    (entry->image_size == 0)) {
1423 			continue;
1424 		}
1425 
1426 		switch (entry->type) {
1427 		case BE_FLASHTYPE_REDBOOT:
1428 			file = &fw_image->file[REDBOOT_FLASHTYPE];
1429 			(void) strlcpy(file->label, "REDBOOT",
1430 			    sizeof (file->label));
1431 			file->type = MGMT_FLASHROM_OPTYPE_REDBOOT;
1432 			break;
1433 		case BE_FLASHTYPE_ISCSI_BIOS:
1434 			file = &fw_image->file[ISCSI_BIOS_FLASHTYPE];
1435 			(void) strlcpy(file->label, "ISCSI BIOS",
1436 			    sizeof (file->label));
1437 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_BIOS;
1438 			break;
1439 		case BE_FLASHTYPE_PXE_BIOS:
1440 			file = &fw_image->file[PXE_BIOS_FLASHTYPE];
1441 			(void) strlcpy(file->label, "PXE BIOS",
1442 			    sizeof (file->label));
1443 			file->type = MGMT_FLASHROM_OPTYPE_PXE_BIOS;
1444 			break;
1445 		case BE_FLASHTYPE_FCOE_BIOS:
1446 			file = &fw_image->file[FCOE_BIOS_FLASHTYPE];
1447 			(void) strlcpy(file->label, "FCOE BIOS",
1448 			    sizeof (file->label));
1449 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_BIOS;
1450 			break;
1451 		case BE_FLASHTYPE_ISCSI_FIRMWARE:
1452 			file = &fw_image->file[ISCSI_FIRMWARE_FLASHTYPE];
1453 			(void) strlcpy(file->label, "ISCSI FIRMWARE",
1454 			    sizeof (file->label));
1455 			file->type = MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE;
1456 			break;
1457 		case BE_FLASHTYPE_FCOE_FIRMWARE:
1458 			file = &fw_image->file[FCOE_FIRMWARE_FLASHTYPE];
1459 			(void) strlcpy(file->label, "FCOE FIRMWARE",
1460 			    sizeof (file->label));
1461 			file->type = MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE;
1462 			break;
1463 		case BE_FLASHTYPE_NCSI_FIRMWARE:
1464 			file = &fw_image->file[NCSI_FIRMWARE_FLASHTYPE];
1465 			(void) strlcpy(file->label, "NCSI FIRMWARE",
1466 			    sizeof (file->label));
1467 			file->type = MGMT_FLASHROM_OPTYPE_NCSI_FIRMWARE;
1468 			break;
1469 		case BE_FLASHTYPE_FLASH_ISM:
1470 		case BE_FLASHTYPE_FCOE_BACKUP:
1471 		case BE_FLASHTYPE_ISCSI_BACKUP:
1472 			continue;
1473 		case BE_FLASHTYPE_PHY_FIRMWARE:
1474 			file = &fw_image->file[PHY_FIRMWARE_FLASHTYPE];
1475 			(void) strlcpy(file->label, "PHY FIRMWARE",
1476 			    sizeof (file->label));
1477 			file->type = MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE;
1478 			break;
1479 
1480 		default:
1481 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1482 			    "Unknown image type found.  type=%x",
1483 			    entry->type);
1484 			continue;
1485 		}
1486 
1487 		file->be_version = fw_image->be_version;
1488 		file->ufi_plus = fw_image->ufi_plus;
1489 		file->image_size = entry->image_size;
1490 
1491 		if (ufi_plus) {
1492 			file->image_offset = entry->offset;
1493 			file->block_size   = entry->block_size;
1494 			file->block_crc    = entry->checksum;
1495 			file->load_address = entry->entry_point;
1496 		} else {
1497 			file->image_offset = entry->offset +
1498 			    flash_image_hdr->offset;
1499 			file->block_size   = entry->block_size;
1500 
1501 			wptr = (uint32_t *)(buffer +  file->image_offset +
1502 			    file->block_size);
1503 
1504 			/* Read load address */
1505 			value = *(wptr - 3);
1506 			file->load_address = BE_SWAP32(value);
1507 
1508 			/* Read block_crc */
1509 			value = *(wptr - 1);
1510 			file->block_crc = BE_SWAP32(value);
1511 		}
1512 
1513 		/* Make sure image will fit in block specified */
1514 		if (file->image_size + 12 > file->block_size) {
1515 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1516 			    "%s: Image too large for block. image=%x block=%x",
1517 			    file->label, file->image_size, file->block_size);
1518 
1519 			bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1520 			return (EMLXS_IMAGE_BAD);
1521 		}
1522 
1523 		/* Automatically create a backup file entry for firmware */
1524 		if (file->type == MGMT_FLASHROM_OPTYPE_FCOE_FIRMWARE) {
1525 			file2 = &fw_image->file[FCOE_BACKUP_FLASHTYPE];
1526 
1527 			bcopy((uint8_t *)file, (uint8_t *)file2,
1528 			    sizeof (emlxs_be_fw_file_t));
1529 			file2->type = MGMT_FLASHROM_OPTYPE_FCOE_BACKUP;
1530 			(void) strlcpy(file2->label, "FCOE BACKUP",
1531 			    sizeof (file2->label));
1532 
1533 			/* Save FCOE version info */
1534 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1535 			(void) strncpy(fw_image->fcoe_label, (char *)bptr,
1536 			    BE_VERSION_SIZE);
1537 			fw_image->fcoe_version = file->block_crc;
1538 
1539 		} else if (file->type ==
1540 		    MGMT_FLASHROM_OPTYPE_ISCSI_FIRMWARE) {
1541 			file2 = &fw_image->file[ISCSI_BACKUP_FLASHTYPE];
1542 
1543 			bcopy((uint8_t *)file, (uint8_t *)file2,
1544 			    sizeof (emlxs_be_fw_file_t));
1545 			file2->type = MGMT_FLASHROM_OPTYPE_ISCSI_BACKUP;
1546 			(void) strlcpy(file2->label, "ISCSI BACKUP",
1547 			    sizeof (file->label));
1548 
1549 			/* Save ISCSI version info */
1550 			bptr = (uint8_t *)buffer + file->image_offset + 0x30;
1551 			(void) strncpy(fw_image->iscsi_label, (char *)bptr,
1552 			    BE_VERSION_SIZE);
1553 			fw_image->iscsi_version = file->block_crc;
1554 		}
1555 	}
1556 
1557 	if (fw_image->fcoe_version == 0) {
1558 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1559 		    "Unable to find FCOE firmware component.");
1560 
1561 		bzero(fw_image, sizeof (emlxs_be_fw_image_t));
1562 		return (EMLXS_IMAGE_BAD);
1563 	}
1564 
1565 	/* Display contents */
1566 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1567 	    "BE3 UFI Image: %08x, %s", fw_image->fcoe_version,
1568 	    fw_image->fcoe_label);
1569 
1570 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1571 		file = &fw_image->file[i];
1572 
1573 		if (file->image_size == 0) {
1574 			continue;
1575 		}
1576 
1577 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
1578 		    "%s: be=%x%s type=%x block=%x image=%x offset=%x crc=%x "
1579 		    "load=%x",
1580 		    file->label, file->be_version, (file->ufi_plus)? "+":"",
1581 		    file->type, file->block_size, file->image_size,
1582 		    file->image_offset, file->block_crc, file->load_address);
1583 	}
1584 
1585 	return (0);
1586 
1587 } /* emlxs_be3_validate_image() */
1588 
1589 
1590 static int32_t
emlxs_be_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)1591 emlxs_be_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1592     uint32_t offline)
1593 {
1594 	emlxs_port_t *port = &PPORT;
1595 	uint32_t i;
1596 	uint32_t update = 0;
1597 	uint32_t rval = 0;
1598 	MAILBOXQ *mbq = NULL;
1599 	MATCHMAP *mp = NULL;
1600 	emlxs_be_fw_image_t fw_image;
1601 	emlxs_be_fw_file_t *file;
1602 	uint32_t be_version;
1603 
1604 	/* For now we will not take the driver offline during a download */
1605 	offline = 0;
1606 
1607 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1608 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1609 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
1610 		return (EMLXS_IMAGE_INCOMPATIBLE);
1611 	}
1612 
1613 	if (!(hba->model_info.chip & EMLXS_BE_CHIPS)) {
1614 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1615 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
1616 		return (EMLXS_IMAGE_INCOMPATIBLE);
1617 	}
1618 
1619 	if (buffer == NULL || len == 0) {
1620 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1621 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
1622 		return (EMLXS_IMAGE_BAD);
1623 	}
1624 
1625 	be_version = emlxs_be_version(buffer, len, 0);
1626 
1627 	switch (be_version) {
1628 	case 0:
1629 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1630 		    "Invalid image provided. Non-UFI format.");
1631 		return (EMLXS_IMAGE_INCOMPATIBLE);
1632 	case 2:
1633 		rval = emlxs_be2_validate_image(hba, buffer, len, &fw_image);
1634 		if (rval) {
1635 			return (rval);
1636 		}
1637 		break;
1638 	case 3:
1639 		rval = emlxs_be3_validate_image(hba, buffer, len, &fw_image);
1640 		if (rval) {
1641 			return (rval);
1642 		}
1643 		break;
1644 	default:
1645 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1646 		    "Invalid image provided. Unknown BE version. (%x)",
1647 		    be_version);
1648 		return (EMLXS_IMAGE_INCOMPATIBLE);
1649 	}
1650 
1651 	/* Allocate resources */
1652 
1653 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
1654 	    KM_SLEEP)) == NULL) {
1655 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1656 		    "Unable to allocate mailbox buffer.");
1657 
1658 		offline = 0;
1659 		rval = EMLXS_IMAGE_FAILED;
1660 		goto done;
1661 	}
1662 
1663 	if ((mp = emlxs_mem_buf_alloc(hba, (sizeof (mbox_req_hdr_t) +
1664 	    sizeof (IOCTL_COMMON_FLASHROM) + BE_MAX_XFER_SIZE))) == NULL) {
1665 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1666 		    "Unable to allocate flash buffer.");
1667 
1668 		offline = 0;
1669 		rval = EMLXS_IMAGE_FAILED;
1670 		goto done;
1671 	}
1672 
1673 	/* Check if update is required */
1674 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1675 		file = &fw_image.file[i];
1676 
1677 		if (file->image_size == 0) {
1678 			continue;
1679 		}
1680 
1681 		if (file->type == MGMT_FLASHROM_OPTYPE_PHY_FIRMWARE) {
1682 			rval = emlxs_be_verify_phy(hba, file, mbq, mp);
1683 
1684 			if (rval != 0) {
1685 				/* Do not update */
1686 				file->image_size = 0;
1687 				continue;
1688 			}
1689 		} else {
1690 			rval = emlxs_be_verify_crc(hba, file, mbq, mp);
1691 			if (rval == 0) {
1692 				/* Do not update */
1693 				file->image_size = 0;
1694 				continue;
1695 			}
1696 		}
1697 
1698 		update++;
1699 	}
1700 
1701 	if (!update) {
1702 		offline = 0;
1703 		rval = 0;
1704 		goto done;
1705 	}
1706 
1707 	/*
1708 	 * Everything checks out, now to just do it
1709 	 */
1710 	if (offline) {
1711 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
1712 
1713 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1714 			    "Unable to take adapter offline.");
1715 
1716 			offline = 0;
1717 			rval = EMLXS_OFFLINE_FAILED;
1718 			goto done;
1719 		}
1720 	}
1721 
1722 	/* Download entries which require update */
1723 	for (i = 0; i < BE_MAX_FLASHTYPES; i++) {
1724 		file = &fw_image.file[i];
1725 
1726 		if (file->image_size == 0) {
1727 			continue;
1728 		}
1729 
1730 		rval = emlxs_be_flash_image(hba, buffer, file, mbq, mp);
1731 
1732 		if (rval != 0) {
1733 			goto done;
1734 		}
1735 	}
1736 
1737 done:
1738 	if (mbq) {
1739 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
1740 	}
1741 
1742 	if (mp) {
1743 		emlxs_mem_buf_free(hba, mp);
1744 	}
1745 
1746 	if (offline) {
1747 		(void) emlxs_online(hba);
1748 	}
1749 
1750 	if (rval == 0) {
1751 		if (update) {
1752 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
1753 			    "Status good.");
1754 
1755 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
1756 			    "The new firmware will not be activated until "
1757 			    "the adapter is power cycled: %s",
1758 			    fw_image.fcoe_label);
1759 
1760 		} else {
1761 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1762 			    "No firmware update required.");
1763 		}
1764 	}
1765 
1766 	return (rval);
1767 
1768 } /* emlxs_be_fw_download() */
1769 
1770 
1771 static int32_t
emlxs_obj_flash_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t size,MAILBOXQ * mbq,MATCHMAP * mp,uint32_t * change_status)1772 emlxs_obj_flash_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t size,
1773     MAILBOXQ *mbq, MATCHMAP *mp, uint32_t *change_status)
1774 {
1775 	emlxs_port_t *port = &PPORT;
1776 	uint8_t *image_ptr;
1777 	MAILBOX4 *mb;
1778 	mbox_req_hdr_t	*hdr_req;
1779 	mbox_rsp_hdr_t	*hdr_rsp;
1780 	uint32_t	image_size;
1781 	uint32_t	xfer_size;
1782 	uint32_t	image_offset;
1783 	uint32_t	rval = 0;
1784 	IOCTL_COMMON_WRITE_OBJECT *write_obj;
1785 	uint32_t 	cstatus = 0;
1786 
1787 	if (!buffer || size == 0) {
1788 		return (0);
1789 	}
1790 
1791 	image_ptr  = (uint8_t *)buffer;
1792 	image_size = size;
1793 	image_offset = 0;
1794 	mb = (MAILBOX4*)mbq;
1795 
1796 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1797 	    "OBJ File: Downloading...");
1798 
1799 	while (image_size) {
1800 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1801 		bzero((void *) mp->virt, mp->size);
1802 
1803 		xfer_size = min(OBJ_MAX_XFER_SIZE, image_size);
1804 
1805 		mb->un.varSLIConfig.be.embedded = 1;
1806 		mbq->nonembed  = NULL;
1807 		mbq->mbox_cmpl = NULL;
1808 
1809 		mb->mbxCommand = MBX_SLI_CONFIG;
1810 		mb->mbxOwner = OWN_HOST;
1811 
1812 		hdr_req = (mbox_req_hdr_t *)
1813 		    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
1814 		hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
1815 		hdr_req->opcode = COMMON_OPCODE_WRITE_OBJ;
1816 		hdr_req->timeout = 0;
1817 
1818 		write_obj = (IOCTL_COMMON_WRITE_OBJECT *)(hdr_req + 1);
1819 		write_obj->params.request.EOF =
1820 		    ((xfer_size == image_size)? 1:0);
1821 		write_obj->params.request.desired_write_length = xfer_size;
1822 		write_obj->params.request.write_offset = image_offset;
1823 
1824 		(void) strlcpy((char *)write_obj->params.request.object_name,
1825 		    "/prg", sizeof (write_obj->params.request.object_name));
1826 		BE_SWAP32_BUFFER((uint8_t *)
1827 		    write_obj->params.request.object_name,
1828 		    sizeof (write_obj->params.request.object_name));
1829 
1830 		write_obj->params.request.buffer_desc_count = 1;
1831 		write_obj->params.request.buffer_length = xfer_size;
1832 		write_obj->params.request.buffer_addrlo = PADDR_LO(mp->phys);
1833 		write_obj->params.request.buffer_addrhi = PADDR_HI(mp->phys);
1834 
1835 		hdr_req->req_length = 116 +
1836 		    (write_obj->params.request.buffer_desc_count * 12);
1837 
1838 		bcopy(image_ptr, mp->virt, xfer_size);
1839 
1840 		hdr_rsp = (mbox_rsp_hdr_t *)
1841 		    &mb->un.varSLIConfig.be.un_hdr.hdr_rsp;
1842 		write_obj = (IOCTL_COMMON_WRITE_OBJECT *)(hdr_rsp + 1);
1843 
1844 		/* Send write request */
1845 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) !=
1846 		    MBX_SUCCESS) {
1847 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1848 			    "OBJ File: Unable to download image. status=%x "
1849 			    "(%x,%x)",
1850 			    mb->mbxStatus, hdr_rsp->status,
1851 			    hdr_rsp->extra_status);
1852 
1853 			return (EMLXS_IMAGE_FAILED);
1854 		}
1855 
1856 		/* Check header status */
1857 		if (hdr_rsp->status) {
1858 			if ((hdr_rsp->status == MBX_RSP_STATUS_FAILED) &&
1859 			    (hdr_rsp->extra_status ==
1860 			    MGMT_ADDI_STATUS_INCOMPATIBLE)) {
1861 				EMLXS_MSGF(EMLXS_CONTEXT,
1862 				    &emlxs_download_failed_msg,
1863 				    "OBJ File: Image file incompatible with "
1864 				    "adapter hardware.");
1865 				return (EMLXS_IMAGE_INCOMPATIBLE);
1866 			}
1867 
1868 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1869 			    "OBJ File: Unable to download image. "
1870 			    "hdr_status=%x,%x size=%d,%d",
1871 			    hdr_rsp->status, hdr_rsp->extra_status,
1872 			    write_obj->params.response.actual_write_length,
1873 			    xfer_size);
1874 
1875 			return (EMLXS_IMAGE_FAILED);
1876 		}
1877 
1878 		/* Check response length */
1879 		if (write_obj->params.response.actual_write_length == 0) {
1880 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1881 			    "OBJ File: No data actually written.");
1882 
1883 			return (EMLXS_IMAGE_FAILED);
1884 		}
1885 
1886 		if (write_obj->params.response.actual_write_length >
1887 		    xfer_size) {
1888 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
1889 			    "OBJ File: Mismatch in data xfer size. "
1890 			    "size=%d,%d offset=%d",
1891 			    write_obj->params.response.actual_write_length,
1892 			    xfer_size, image_offset);
1893 
1894 			return (EMLXS_IMAGE_FAILED);
1895 		}
1896 
1897 		/* Set xfer_size to actual write length */
1898 		xfer_size = write_obj->params.response.actual_write_length;
1899 
1900 		image_ptr  += xfer_size;
1901 		image_offset += xfer_size;
1902 		image_size -= xfer_size;
1903 
1904 		if (image_size == 0) {
1905 			cstatus = write_obj->params.response.change_status;
1906 		}
1907 	}
1908 
1909 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
1910 	    "OBJ File: Download complete. (cstatus=%d)",
1911 	    cstatus);
1912 
1913 	if (change_status) {
1914 		*change_status = cstatus;
1915 	}
1916 
1917 	return (rval);
1918 
1919 } /* emlxs_obj_flash_image() */
1920 
1921 
1922 static uint32_t
emlxs_obj_validate_image(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,emlxs_obj_header_t * obj_hdr_in)1923 emlxs_obj_validate_image(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
1924     emlxs_obj_header_t *obj_hdr_in)
1925 {
1926 	emlxs_port_t *port = &PPORT;
1927 	emlxs_obj_header_t obj_hdr;
1928 
1929 	if (obj_hdr_in) {
1930 		bzero(obj_hdr_in, sizeof (emlxs_obj_header_t));
1931 	}
1932 
1933 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1934 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1935 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
1936 		return (EMLXS_IMAGE_INCOMPATIBLE);
1937 	}
1938 
1939 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
1940 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1941 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
1942 		return (EMLXS_IMAGE_INCOMPATIBLE);
1943 	}
1944 
1945 	if (len < sizeof (emlxs_obj_header_t)) {
1946 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1947 		    "Image too small. (%d < %d)",
1948 		    len,  sizeof (emlxs_obj_header_t));
1949 
1950 		return (EMLXS_IMAGE_BAD);
1951 	}
1952 
1953 	bcopy(buffer, (uint8_t *)&obj_hdr, sizeof (emlxs_obj_header_t));
1954 
1955 	/* Swap first 3 words */
1956 	LE_SWAP32_BUFFER((uint8_t *)&obj_hdr, 12);
1957 
1958 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1959 	    "Object Header: size=%d magic=%04x,%04x type=%02x id=%02x",
1960 	    obj_hdr.FileSize,
1961 	    obj_hdr.MagicNumHi, obj_hdr.MagicNumLo,
1962 	    obj_hdr.FileType,
1963 	    obj_hdr.Id);
1964 
1965 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1966 	    "Object Header: Date=%s Rev=%s",
1967 	    obj_hdr.Date,
1968 	    obj_hdr.Revision);
1969 
1970 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
1971 	    "Object Header: Name=%s",
1972 	    obj_hdr.RevName);
1973 
1974 	if ((obj_hdr.MagicNumHi != OBJ_MAGIC_NUM_HI) ||
1975 	    (obj_hdr.MagicNumLo != OBJ_MAGIC_NUM_LO)) {
1976 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1977 		    "Wrong Magic Number: %x,%x",
1978 		    obj_hdr.MagicNumHi, obj_hdr.MagicNumLo);
1979 
1980 		return (EMLXS_IMAGE_INCOMPATIBLE);
1981 	}
1982 
1983 	if (obj_hdr.FileSize != len) {
1984 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
1985 		    "Image too small. (%d < %d)",
1986 		    len, obj_hdr.FileSize);
1987 
1988 		return (EMLXS_IMAGE_BAD);
1989 	}
1990 
1991 	if ((hba->model_info.chip & EMLXS_LANCER_CHIP) &&
1992 	    (obj_hdr.Id != OBJ_LANCER_ID)) {
1993 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
1994 		    "Invalid adapter model. chip=%x fwid=%x",
1995 		    hba->model_info.chip,
1996 		    obj_hdr.Id);
1997 		return (EMLXS_IMAGE_INCOMPATIBLE);
1998 	}
1999 
2000 	if (obj_hdr_in) {
2001 		bcopy(&obj_hdr, obj_hdr_in, sizeof (emlxs_obj_header_t));
2002 	}
2003 
2004 	return (0);
2005 
2006 } /* emlxs_obj_validate_image() */
2007 
2008 
2009 static int32_t
emlxs_obj_fw_download(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline)2010 emlxs_obj_fw_download(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
2011     uint32_t offline)
2012 {
2013 	emlxs_port_t *port = &PPORT;
2014 	uint32_t rval = 0;
2015 	MAILBOXQ *mbq = NULL;
2016 	MATCHMAP *mp = NULL;
2017 	uint32_t change_status = 0;
2018 
2019 	/* For now we will not take the driver offline during a download */
2020 	offline = 0;
2021 
2022 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
2023 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2024 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
2025 		return (EMLXS_IMAGE_INCOMPATIBLE);
2026 	}
2027 
2028 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
2029 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2030 		    "Invalid adapter model. chip=%x", hba->model_info.chip);
2031 		return (EMLXS_IMAGE_INCOMPATIBLE);
2032 	}
2033 
2034 	if (buffer == NULL || len == 0) {
2035 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2036 		    "Empty buffer provided. buf=%p size=%d", buffer, len);
2037 		return (EMLXS_IMAGE_BAD);
2038 	}
2039 
2040 	rval = emlxs_obj_validate_image(hba, buffer, len, 0);
2041 
2042 	if (rval) {
2043 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
2044 		    "Invalid image provided.");
2045 		return (EMLXS_IMAGE_INCOMPATIBLE);
2046 	}
2047 
2048 	/* Allocate resources */
2049 
2050 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2051 	    KM_SLEEP)) == NULL) {
2052 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2053 		    "Unable to allocate mailbox buffer.");
2054 
2055 		offline = 0;
2056 		rval = EMLXS_IMAGE_FAILED;
2057 		goto done;
2058 	}
2059 
2060 	if ((mp = emlxs_mem_buf_alloc(hba, OBJ_MAX_XFER_SIZE)) == NULL) {
2061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2062 		    "Unable to allocate flash buffer.");
2063 
2064 		offline = 0;
2065 		rval = EMLXS_IMAGE_FAILED;
2066 		goto done;
2067 	}
2068 
2069 	/*
2070 	 * Everything checks out, now to just do it
2071 	 */
2072 	if (offline) {
2073 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
2074 
2075 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2076 			    "Unable to take adapter offline.");
2077 
2078 			offline = 0;
2079 			rval = EMLXS_OFFLINE_FAILED;
2080 			goto done;
2081 		}
2082 	}
2083 
2084 	rval = emlxs_obj_flash_image(hba, buffer, len, mbq, mp, &change_status);
2085 
2086 done:
2087 	if (mbq) {
2088 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2089 	}
2090 
2091 	if (mp) {
2092 		emlxs_mem_buf_free(hba, mp);
2093 	}
2094 
2095 	if (offline) {
2096 		(void) emlxs_online(hba);
2097 	}
2098 
2099 	if (rval == 0) {
2100 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
2101 		    "Status good.");
2102 
2103 		switch (change_status) {
2104 		case CS_NO_RESET:
2105 			break;
2106 
2107 		case CS_REBOOT_RQD:
2108 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
2109 			    "The new firmware will not be activated until "
2110 			    "the adapter is power cycled.");
2111 			rval = EMLXS_REBOOT_REQUIRED;
2112 			break;
2113 
2114 		case CS_FW_RESET_RQD:
2115 		case CS_PROTO_RESET_RQD:
2116 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fw_updated_msg,
2117 			    "Resetting all ports to activate new firmware.");
2118 
2119 			emlxs_sli4_hba_reset_all(hba, 0);
2120 		}
2121 	}
2122 
2123 	return (rval);
2124 
2125 } /* emlxs_obj_fw_download() */
2126 
2127 
2128 extern int32_t
emlxs_cfl_download(emlxs_hba_t * hba,uint32_t region,caddr_t buffer,uint32_t len)2129 emlxs_cfl_download(emlxs_hba_t *hba, uint32_t region, caddr_t buffer,
2130     uint32_t len)
2131 {
2132 	emlxs_port_t *port = &PPORT;
2133 	MAILBOXQ *mbox = NULL;
2134 	MAILBOX *mb;
2135 	uint32_t rval = 0;
2136 	uint32_t region_id;
2137 	uint32_t id;
2138 #ifdef EMLXS_BIG_ENDIAN
2139 	caddr_t local_buffer;
2140 	uint32_t *bptr1;
2141 	uint32_t *bptr2;
2142 	uint32_t i;
2143 #endif /* EMLXS_BIG_ENDIAN */
2144 
2145 	if (buffer == NULL || len == 0) {
2146 		return (EMLXS_IMAGE_BAD);
2147 	}
2148 
2149 #ifdef EMLXS_BIG_ENDIAN
2150 	/* We need to swap the image buffer before we start */
2151 
2152 	/*
2153 	 * Use KM_SLEEP to allocate a temporary buffer
2154 	 */
2155 	local_buffer = (caddr_t)kmem_zalloc(len, KM_SLEEP);
2156 
2157 	/* Perform a 32 bit swap of the image */
2158 	bptr1 = (uint32_t *)local_buffer;
2159 	bptr2 = (uint32_t *)buffer;
2160 
2161 	for (i = 0; i < (len / 4); i++) {
2162 		*bptr1 = SWAP32(*bptr2);
2163 		bptr1++;
2164 		bptr2++;
2165 	}
2166 
2167 	/* Replace the original buffer */
2168 	buffer = local_buffer;
2169 
2170 #endif /* EMLXS_BIG_ENDIAN */
2171 
2172 	if (len > 128) {
2173 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2174 		    "Invalid image length: 0x%x > 128", len);
2175 
2176 		return (EMLXS_IMAGE_BAD);
2177 	}
2178 
2179 	/* Check the region number */
2180 	if ((region > 2) && (region != 0xff)) {
2181 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2182 		    "Invalid region id: 0x%x", region);
2183 
2184 		return (EMLXS_IMAGE_BAD);
2185 
2186 	}
2187 
2188 	/* Check the image vendor id */
2189 	id = *(int32_t *)buffer;
2190 	if ((id & 0xffff) != 0x10df) {
2191 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
2192 		    "Invalid image id: 0x%x", id);
2193 
2194 		return (EMLXS_IMAGE_BAD);
2195 	}
2196 
2197 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2198 	    KM_NOSLEEP)) == NULL) {
2199 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2200 		    "Unable to allocate mailbox buffer.");
2201 
2202 		rval = 1;
2203 
2204 		goto done;
2205 	}
2206 
2207 	mb = (MAILBOX *)mbox;
2208 
2209 	/*
2210 	 * Everything checks out, now to just do it
2211 	 */
2212 	if (emlxs_offline(hba, 0) != FC_SUCCESS) {
2213 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2214 		    "Unable to take HBA offline.");
2215 
2216 		rval = EMLXS_OFFLINE_FAILED;
2217 
2218 		goto done;
2219 	}
2220 
2221 	if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
2222 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2223 		    "Unable to restart adapter.");
2224 
2225 		rval = EMLXS_OFFLINE_FAILED;
2226 
2227 		goto done;
2228 	}
2229 
2230 	/* Check if default region is requested */
2231 	if (region == 0xff) {
2232 		/*
2233 		 * Sun-branded Helios and Zypher have different
2234 		 * default PCI region
2235 		 */
2236 		if ((hba->model_info.flags & EMLXS_ORACLE_BRANDED) &&
2237 		    (hba->model_info.chip &
2238 		    (EMLXS_HELIOS_CHIP | EMLXS_ZEPHYR_CHIP))) {
2239 			region = 2;
2240 		} else {
2241 			region = 0;
2242 		}
2243 	}
2244 
2245 	/* Set region id based on PCI region requested */
2246 	region_id = DEF_PCI_CFG_REGION_ID + region;
2247 
2248 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2249 	    "PCI configuration: PCI%d region=%d id=0x%x size=%d", region,
2250 	    region_id, id, len);
2251 
2252 	/* Copy the data buffer to SLIM */
2253 	WRITE_SLIM_COPY(hba, (uint32_t *)buffer,
2254 	    (volatile uint32_t *)((volatile char *)hba->sli.sli3.slim_addr +
2255 	    sizeof (MAILBOX)), (len / sizeof (uint32_t)));
2256 
2257 #ifdef FMA_SUPPORT
2258 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2259 	    != DDI_FM_OK) {
2260 		EMLXS_MSGF(EMLXS_CONTEXT,
2261 		    &emlxs_invalid_access_handle_msg, NULL);
2262 		rval = 1;
2263 	}
2264 #endif  /* FMA_SUPPORT */
2265 
2266 	emlxs_format_update_pci_cfg(hba, mbox, region_id, len);
2267 
2268 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2269 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2270 		    "Unable to update PCI configuration: Mailbox cmd=%x "
2271 		    "status=%x info=%d", mb->mbxCommand, mb->mbxStatus,
2272 		    mb->un.varUpdateCfg.rsp_info);
2273 
2274 		rval = 1;
2275 	}
2276 
2277 	(void) emlxs_online(hba);
2278 
2279 	if (rval == 0) {
2280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_complete_msg,
2281 		    "Status good.");
2282 	}
2283 
2284 done:
2285 
2286 	if (mbox) {
2287 		kmem_free(mbox, sizeof (MAILBOXQ));
2288 	}
2289 
2290 #ifdef EMLXS_BIG_ENDIAN
2291 	/* Free the local buffer */
2292 	kmem_free(local_buffer, len);
2293 #endif /* EMLXS_BIG_ENDIAN */
2294 
2295 	return (rval);
2296 
2297 } /* emlxs_cfl_download */
2298 
2299 
2300 static uint32_t
emlxs_valid_cksum(uint32_t * StartAddr,uint32_t * EndAddr)2301 emlxs_valid_cksum(uint32_t *StartAddr, uint32_t *EndAddr)
2302 {
2303 	uint32_t Temp;
2304 	uint32_t CkSum;
2305 
2306 	EndAddr++;
2307 	CkSum = SLI_CKSUM_SEED;
2308 
2309 	CkSum = (CkSum >> 1) | (CkSum << 31);
2310 	while (StartAddr != EndAddr) {
2311 		CkSum = (CkSum << 1) | (CkSum >> 31);
2312 		Temp = *StartAddr;
2313 
2314 		CkSum ^= Temp;
2315 		StartAddr++;
2316 	}
2317 
2318 	return (CkSum << 1) | (CkSum >> 31);
2319 
2320 } /* emlxs_valid_cksum() */
2321 
2322 
2323 static void
emlxs_disp_aif_header(emlxs_hba_t * hba,PAIF_HDR AifHdr)2324 emlxs_disp_aif_header(emlxs_hba_t *hba, PAIF_HDR AifHdr)
2325 {
2326 	emlxs_port_t *port = &PPORT;
2327 
2328 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "AIF Header: ");
2329 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2330 	    "AIF Header: compress_br = 0x%x", AifHdr->CompressBr);
2331 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2332 	    "AIF Header: reloc_br = 0x%x", AifHdr->RelocBr);
2333 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2334 	    "AIF Header: zinit_br = 0x%x", AifHdr->ZinitBr);
2335 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2336 	    "AIF Header: entry_br = 0x%x", AifHdr->EntryBr);
2337 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2338 	    "AIF Header: area_id = 0x%x", AifHdr->Area_ID);
2339 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2340 	    "AIF Header: rosize = 0x%x", AifHdr->RoSize);
2341 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2342 	    "AIF Header: dbgsize = 0x%x", AifHdr->DbgSize);
2343 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2344 	    "AIF Header: zinitsize = 0x%x", AifHdr->ZinitSize);
2345 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2346 	    "AIF Header: dbgtype = 0x%x", AifHdr->DbgType);
2347 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2348 	    "AIF Header: imagebase = 0x%x", AifHdr->ImageBase);
2349 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2350 	    "AIF Header: area_size = 0x%x", AifHdr->Area_Size);
2351 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2352 	    "AIF Header: address_mode = 0x%x", AifHdr->AddressMode);
2353 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2354 	    "AIF Header: database = 0x%x", AifHdr->DataBase);
2355 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2356 	    "AIF Header: aversion = 0x%x", AifHdr->AVersion);
2357 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2358 	    "AIF Header: spare2 = 0x%x", AifHdr->Spare2);
2359 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2360 	    "AIF Header: debug_swi = 0x%x", AifHdr->DebugSwi);
2361 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2362 	    "AIF Header: zinitcode[0] = 0x%x", AifHdr->ZinitCode[0]);
2363 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2364 	    "AIF Header: zinitcode[1] = 0x%x", AifHdr->ZinitCode[1]);
2365 
2366 } /* emlxs_disp_aif_header() */
2367 
2368 
2369 
2370 static void
emlxs_dump_image_header(emlxs_hba_t * hba,PIMAGE_HDR image)2371 emlxs_dump_image_header(emlxs_hba_t *hba, PIMAGE_HDR image)
2372 {
2373 	emlxs_port_t *port = &PPORT;
2374 
2375 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Img Header: ");
2376 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2377 	    "Img Header: BlockSize = 0x%x", image->BlockSize);
2378 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2379 	    "Img Header: PROG_ID Type = 0x%x", image->Id.Type);
2380 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2381 	    "Img Header: PROG_ID Id = 0x%x", image->Id.Id);
2382 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2383 	    "Img Header: PROG_ID Ver = 0x%x", image->Id.Ver);
2384 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2385 	    "Img Header: PROG_ID Rev = 0x%x", image->Id.Rev);
2386 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2387 	    "Img Header: PROG_ID revcomp = 0x%x", image->Id.un.revcomp);
2388 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2389 	    "Img Header: Flags = 0x%x", image->Flags);
2390 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2391 	    "Img Header: EntryAdr = 0x%x", image->EntryAdr);
2392 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2393 	    "Img Header: InitAdr = 0x%x", image->InitAdr);
2394 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2395 	    "Img Header: ExitAdr = 0x%x", image->ExitAdr);
2396 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2397 	    "Img Header: ImageBase = 0x%x", image->ImageBase);
2398 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2399 	    "Img Header: ImageSize = 0x%x", image->ImageSize);
2400 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2401 	    "Img Header: ZinitSize = 0x%x", image->ZinitSize);
2402 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2403 	    "Img Header: RelocSize = 0x%x", image->RelocSize);
2404 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2405 	    "Img Header: HdrCks = 0x%x", image->HdrCks);
2406 
2407 } /* emlxs_dump_image_header() */
2408 
2409 
2410 static void
emlxs_format_dump(emlxs_hba_t * hba,MAILBOXQ * mbq,uint32_t Type,uint32_t RegionId,uint32_t WordCount,uint32_t BaseAddr)2411 emlxs_format_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t Type,
2412     uint32_t RegionId, uint32_t WordCount, uint32_t BaseAddr)
2413 {
2414 
2415 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2416 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
2417 
2418 		/* Clear the local dump_region */
2419 		bzero(hba->sli.sli4.dump_region.virt,
2420 		    hba->sli.sli4.dump_region.size);
2421 
2422 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
2423 
2424 		mb->mbxCommand = MBX_DUMP_MEMORY;
2425 		mb->un.varDmp4.type = Type;
2426 		mb->un.varDmp4.entry_index = BaseAddr;
2427 		mb->un.varDmp4.region_id = RegionId;
2428 
2429 		mb->un.varDmp4.available_cnt = min((WordCount*4),
2430 		    hba->sli.sli4.dump_region.size);
2431 		mb->un.varDmp4.addrHigh =
2432 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
2433 		mb->un.varDmp4.addrLow =
2434 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
2435 		mb->un.varDmp4.rsp_cnt = 0;
2436 
2437 		mb->mbxOwner = OWN_HOST;
2438 
2439 	} else {
2440 		MAILBOX *mb = (MAILBOX *)mbq;
2441 
2442 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
2443 
2444 		mb->mbxCommand = MBX_DUMP_MEMORY;
2445 		mb->un.varDmp.type = Type;
2446 		mb->un.varDmp.region_id = RegionId;
2447 		mb->un.varDmp.word_cnt = WordCount;
2448 		mb->un.varDmp.base_adr = BaseAddr;
2449 		mb->mbxOwner = OWN_HOST;
2450 	}
2451 
2452 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2453 
2454 	return;
2455 
2456 } /* emlxs_format_dump() */
2457 
2458 
2459 /* ARGSUSED */
2460 static uint32_t
emlxs_start_abs_download(emlxs_hba_t * hba,PAIF_HDR AifHdr,caddr_t Buffer,uint32_t len,PWAKE_UP_PARMS WakeUpParms)2461 emlxs_start_abs_download(emlxs_hba_t *hba,
2462     PAIF_HDR AifHdr,
2463     caddr_t Buffer,
2464     uint32_t len,
2465     PWAKE_UP_PARMS WakeUpParms)
2466 {
2467 	emlxs_port_t *port = &PPORT;
2468 	uint32_t DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
2469 	uint32_t *Src;
2470 	uint32_t *Dst;
2471 	caddr_t DataBuffer = NULL;
2472 	MAILBOXQ *mbox;
2473 	MAILBOX *mb;
2474 	uint32_t rval = 1;
2475 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
2476 	uint32_t DlToAddr = AifHdr->ImageBase;
2477 	uint32_t DlCount;
2478 	uint32_t i;
2479 	WAKE_UP_PARMS AbsWakeUpParms;
2480 	int32_t AbsChangeParams;
2481 
2482 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2483 	    "Performing absolute download...");
2484 
2485 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
2486 	    KM_NOSLEEP)) == NULL) {
2487 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2488 		    "Unable to allocate data buffer.");
2489 
2490 		return (rval);
2491 	}
2492 
2493 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2494 	    KM_NOSLEEP)) == NULL) {
2495 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2496 		    "Unable to allocate mailbox buffer.");
2497 
2498 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2499 
2500 		return (rval);
2501 	}
2502 	mb = (MAILBOX *)mbox;
2503 
2504 	AbsChangeParams = emlxs_build_parms(Buffer,
2505 	    &AbsWakeUpParms, len, AifHdr);
2506 
2507 	Buffer += sizeof (AIF_HDR);
2508 
2509 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg, "Erasing flash...");
2510 
2511 	if (AifHdr->ImageBase == 0x20000) {
2512 		/* DWC File */
2513 		emlxs_format_prog_flash(mbox, 0x20000, 0x50000, ERASE_FLASH, 0,
2514 		    0, 0, NULL, 0);
2515 	} else {
2516 		emlxs_format_prog_flash(mbox, DlToAddr, DlByteCount,
2517 		    ERASE_FLASH, 0, 0, 0, NULL, 0);
2518 	}
2519 
2520 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2521 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2522 		    "Unable to erase Flash: Mailbox cmd=%x status=%x",
2523 		    mb->mbxCommand, mb->mbxStatus);
2524 
2525 		rval = 1;
2526 
2527 		goto EXIT_ABS_DOWNLOAD;
2528 	}
2529 
2530 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
2531 	    "Programming flash...");
2532 
2533 	while (DlByteCount) {
2534 
2535 		if (DlByteCount > SegSize) {
2536 			DlCount = SegSize;
2537 		} else {
2538 			DlCount = DlByteCount;
2539 		}
2540 		DlByteCount -= DlCount;
2541 
2542 		Dst = (uint32_t *)DataBuffer;
2543 		Src = (uint32_t *)Buffer;
2544 
2545 		for (i = 0; i < (DlCount / 4); i++) {
2546 			*Dst = *Src;
2547 			Dst++;
2548 			Src++;
2549 		}
2550 
2551 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
2552 		    (volatile uint32_t *)
2553 		    ((volatile char *)hba->sli.sli3.slim_addr +
2554 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
2555 
2556 		emlxs_format_prog_flash(mbox, DlToAddr, DlCount,
2557 		    PROGRAM_FLASH, (DlByteCount) ? 0 : 1, 0, DlCount, NULL, 0);
2558 
2559 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
2560 		    MBX_SUCCESS) {
2561 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2562 			    "Unable to program Flash: Mailbox cmd=%x status=%x",
2563 			    mb->mbxCommand, mb->mbxStatus);
2564 
2565 			rval = 1;
2566 
2567 			goto EXIT_ABS_DOWNLOAD;
2568 		}
2569 
2570 		Buffer += DlCount;
2571 		DlToAddr += DlCount;
2572 	}
2573 
2574 #ifdef FMA_SUPPORT
2575 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
2576 	    != DDI_FM_OK) {
2577 		EMLXS_MSGF(EMLXS_CONTEXT,
2578 		    &emlxs_invalid_access_handle_msg, NULL);
2579 
2580 		rval = 1;
2581 
2582 		goto EXIT_ABS_DOWNLOAD;
2583 	}
2584 #endif  /* FMA_SUPPORT */
2585 
2586 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg, "Updating params...");
2587 
2588 	if (AbsChangeParams) {
2589 		rval =
2590 		    emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
2591 		    WakeUpParms);
2592 	}
2593 
2594 EXIT_ABS_DOWNLOAD:
2595 	if (DataBuffer) {
2596 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
2597 	}
2598 
2599 	if (mbox) {
2600 		kmem_free(mbox, sizeof (MAILBOXQ));
2601 	}
2602 
2603 	return (rval);
2604 
2605 } /* emlxs_start_abs_download() */
2606 
2607 
2608 /* ARGSUSED */
2609 static void
emlxs_format_prog_flash(MAILBOXQ * mbq,uint32_t Base,uint32_t DlByteCount,uint32_t Function,uint32_t Complete,uint32_t BdeAddress,uint32_t BdeSize,PROG_ID * ProgId,uint32_t keep)2610 emlxs_format_prog_flash(MAILBOXQ *mbq,
2611     uint32_t Base,
2612     uint32_t DlByteCount,
2613     uint32_t Function,
2614     uint32_t Complete,
2615     uint32_t BdeAddress,
2616     uint32_t BdeSize,
2617     PROG_ID *ProgId,
2618     uint32_t keep)
2619 {
2620 	MAILBOX *mb = (MAILBOX *)mbq;
2621 
2622 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2623 
2624 	if (ProgId) {
2625 		mb->mbxCommand = MBX_DOWN_LOAD;
2626 	} else {
2627 		mb->mbxCommand = MBX_LOAD_SM;
2628 	}
2629 
2630 	mb->un.varLdSM.load_cmplt = Complete;
2631 	mb->un.varLdSM.method = DL_FROM_SLIM;
2632 	mb->un.varLdSM.update_flash = 1;
2633 	mb->un.varLdSM.erase_or_prog = Function;
2634 	mb->un.varLdSM.dl_to_adr = Base;
2635 	mb->un.varLdSM.dl_len = DlByteCount;
2636 	mb->un.varLdSM.keep = keep;
2637 
2638 	if (BdeSize) {
2639 		mb->un.varLdSM.un.dl_from_slim_offset = DL_FROM_SLIM_OFFSET;
2640 	} else if (ProgId) {
2641 		mb->un.varLdSM.un.prog_id = *ProgId;
2642 	} else {
2643 		mb->un.varLdSM.un.dl_from_slim_offset = 0;
2644 	}
2645 
2646 	mb->mbxOwner = OWN_HOST;
2647 	mbq->mbox_cmpl = NULL;
2648 
2649 } /* emlxs_format_prog_flash() */
2650 
2651 
2652 static void
emlxs_format_update_parms(MAILBOXQ * mbq,PWAKE_UP_PARMS WakeUpParms)2653 emlxs_format_update_parms(MAILBOXQ *mbq, PWAKE_UP_PARMS WakeUpParms)
2654 {
2655 	MAILBOX *mb = (MAILBOX *)mbq;
2656 
2657 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2658 
2659 	mb->mbxCommand = MBX_UPDATE_CFG;
2660 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2661 	mb->un.varUpdateCfg.region_id = WAKE_UP_PARMS_REGION_ID;
2662 	mb->un.varUpdateCfg.entry_len = sizeof (WAKE_UP_PARMS);
2663 	mb->un.varUpdateCfg.byte_len = sizeof (WAKE_UP_PARMS);
2664 
2665 	bcopy((caddr_t)WakeUpParms,
2666 	    (caddr_t)&(mb->un.varUpdateCfg.cfg_data),
2667 	    sizeof (WAKE_UP_PARMS));
2668 	mbq->mbox_cmpl = NULL;
2669 
2670 } /* emlxs_format_update_parms () */
2671 
2672 
2673 /* ARGSUSED */
2674 static void
emlxs_format_update_pci_cfg(emlxs_hba_t * hba,MAILBOXQ * mbq,uint32_t region_id,uint32_t size)2675 emlxs_format_update_pci_cfg(emlxs_hba_t *hba, MAILBOXQ *mbq,
2676     uint32_t region_id, uint32_t size)
2677 {
2678 	MAILBOX *mb = (MAILBOX *)mbq;
2679 
2680 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2681 
2682 	mb->mbxCommand = MBX_UPDATE_CFG;
2683 	mb->un.varUpdateCfg.Vbit = 1;
2684 	mb->un.varUpdateCfg.Obit = 1;
2685 	mb->un.varUpdateCfg.cfg_data = DL_FROM_SLIM_OFFSET;
2686 	mb->un.varUpdateCfg.req_type = UPDATE_DATA;
2687 	mb->un.varUpdateCfg.region_id = region_id;
2688 	mb->un.varUpdateCfg.entry_len = size;
2689 	mb->un.varUpdateCfg.byte_len = size;
2690 	mbq->mbox_cmpl = NULL;
2691 
2692 } /* emlxs_format_update_pci_cfg() */
2693 
2694 
2695 
2696 static uint32_t
emlxs_update_boot_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id,uint32_t proc_erom)2697 emlxs_update_boot_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2698     PROG_ID * prog_id, uint32_t proc_erom)
2699 {
2700 	emlxs_port_t *port = &PPORT;
2701 	MAILBOX *mb;
2702 	MAILBOXQ *mbox;
2703 	uint32_t rval = 0;
2704 	PROG_ID old_prog_id;
2705 
2706 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2707 	    KM_NOSLEEP)) == NULL) {
2708 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2709 		    "Unable to allocate mailbox buffer.");
2710 
2711 		return (1);
2712 	}
2713 
2714 	mb = (MAILBOX *)mbox;
2715 
2716 	if (proc_erom && !(hba->model_info.chip &
2717 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
2718 		WakeUpParms->u1.EROM_prog_id = *prog_id;
2719 		(void) emlxs_update_exp_rom(hba, WakeUpParms);
2720 	}
2721 
2722 	old_prog_id = WakeUpParms->u0.boot_bios_id;
2723 	WakeUpParms->u0.boot_bios_id = *prog_id;
2724 
2725 	emlxs_format_update_parms(mbox, WakeUpParms);
2726 
2727 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2728 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2729 		    "Unable to update boot wakeup parms: Mailbox cmd=%x "
2730 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2731 
2732 		WakeUpParms->u0.boot_bios_id = old_prog_id;
2733 		rval = 1;
2734 	}
2735 
2736 	if (mbox) {
2737 		kmem_free(mbox, sizeof (MAILBOXQ));
2738 	}
2739 
2740 	return (rval);
2741 
2742 } /* emlxs_update_boot_wakeup_parms() */
2743 
2744 
2745 
2746 static uint32_t
emlxs_update_ff_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2747 emlxs_update_ff_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2748     PROG_ID *prog_id)
2749 {
2750 	emlxs_port_t *port = &PPORT;
2751 	uint32_t rval = 0;
2752 	MAILBOXQ *mbox;
2753 	MAILBOX *mb;
2754 	PROG_ID old_prog_id;
2755 
2756 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2757 	    KM_NOSLEEP)) == NULL) {
2758 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2759 		    "Unable to allocate mailbox buffer.");
2760 
2761 		return (1);
2762 	}
2763 
2764 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2765 	    "FF: Updating parms...");
2766 
2767 	mb = (MAILBOX *)mbox;
2768 
2769 	old_prog_id = WakeUpParms->prog_id;
2770 	WakeUpParms->prog_id = *prog_id;
2771 
2772 	emlxs_format_update_parms(mbox, WakeUpParms);
2773 
2774 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2776 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
2777 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2778 
2779 		WakeUpParms->prog_id = old_prog_id;
2780 		rval = 1;
2781 	}
2782 
2783 	if (mbox) {
2784 		kmem_free(mbox, sizeof (MAILBOXQ));
2785 	}
2786 
2787 	return (rval);
2788 
2789 } /* emlxs_update_ff_wakeup_parms() */
2790 
2791 
2792 static uint32_t
emlxs_update_sli1_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2793 emlxs_update_sli1_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2794     PROG_ID * prog_id)
2795 {
2796 	emlxs_port_t *port = &PPORT;
2797 	uint32_t rval = 0;
2798 	MAILBOXQ *mbox;
2799 	MAILBOX *mb;
2800 	PROG_ID old_prog_id;
2801 
2802 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2803 	    KM_NOSLEEP)) == NULL) {
2804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2805 		    "Unable to allocate mailbox buffer.");
2806 
2807 		return (1);
2808 	}
2809 
2810 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2811 	    "SLI1: Updating parms...");
2812 
2813 	mb = (MAILBOX *)mbox;
2814 
2815 	old_prog_id = WakeUpParms->sli1_prog_id;
2816 	WakeUpParms->sli1_prog_id = *prog_id;
2817 
2818 	emlxs_format_update_parms(mbox, WakeUpParms);
2819 
2820 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2821 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2822 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2823 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2824 
2825 		WakeUpParms->sli1_prog_id = old_prog_id;
2826 		rval = 1;
2827 	}
2828 
2829 	if (mbox) {
2830 		kmem_free(mbox, sizeof (MAILBOXQ));
2831 	}
2832 
2833 	return (rval);
2834 
2835 } /* emlxs_update_sli1_wakeup_parms() */
2836 
2837 
2838 static uint32_t
emlxs_update_sli2_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2839 emlxs_update_sli2_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2840     PROG_ID * prog_id)
2841 {
2842 	emlxs_port_t *port = &PPORT;
2843 	uint32_t rval = 0;
2844 	MAILBOXQ *mbox;
2845 	MAILBOX *mb;
2846 	PROG_ID old_prog_id;
2847 
2848 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2849 	    KM_NOSLEEP)) == NULL) {
2850 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2851 		    "Unable to allocate mailbox buffer.");
2852 
2853 		return (1);
2854 	}
2855 
2856 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2857 	    "SLI2: Updating parms...");
2858 
2859 	mb = (MAILBOX *)mbox;
2860 
2861 	old_prog_id = WakeUpParms->sli2_prog_id;
2862 	WakeUpParms->sli2_prog_id = *prog_id;
2863 
2864 	emlxs_format_update_parms(mbox, WakeUpParms);
2865 
2866 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2867 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2868 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2869 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2870 
2871 		WakeUpParms->sli2_prog_id = old_prog_id;
2872 		rval = 1;
2873 	}
2874 
2875 	if (mbox) {
2876 		kmem_free(mbox, sizeof (MAILBOXQ));
2877 	}
2878 
2879 	return (rval);
2880 
2881 } /* emlxs_update_sli2_wakeup_parms() */
2882 
2883 
2884 static uint32_t
emlxs_update_sli3_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2885 emlxs_update_sli3_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2886     PROG_ID *prog_id)
2887 {
2888 	emlxs_port_t *port = &PPORT;
2889 	uint32_t rval = 0;
2890 	MAILBOXQ *mbox;
2891 	MAILBOX *mb;
2892 	PROG_ID old_prog_id;
2893 
2894 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2895 	    KM_NOSLEEP)) == NULL) {
2896 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2897 		    "Unable to allocate mailbox buffer.");
2898 
2899 		return (1);
2900 	}
2901 
2902 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2903 	    "SLI3: Updating parms...");
2904 
2905 	mb = (MAILBOX *)mbox;
2906 
2907 	old_prog_id = WakeUpParms->sli3_prog_id;
2908 	WakeUpParms->sli3_prog_id = *prog_id;
2909 
2910 	emlxs_format_update_parms(mbox, WakeUpParms);
2911 
2912 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2913 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2914 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2915 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2916 
2917 		WakeUpParms->sli3_prog_id = old_prog_id;
2918 		rval = 1;
2919 	}
2920 
2921 	if (mbox) {
2922 		kmem_free(mbox, sizeof (MAILBOXQ));
2923 	}
2924 
2925 	return (rval);
2926 
2927 } /* emlxs_update_sli3_wakeup_parms() */
2928 
2929 
2930 static uint32_t
emlxs_update_sli4_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,PROG_ID * prog_id)2931 emlxs_update_sli4_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
2932     PROG_ID *prog_id)
2933 {
2934 	emlxs_port_t *port = &PPORT;
2935 	uint32_t rval = 0;
2936 	MAILBOXQ *mbox;
2937 	MAILBOX *mb;
2938 	PROG_ID old_prog_id;
2939 
2940 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
2941 	    KM_NOSLEEP)) == NULL) {
2942 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2943 		    "Unable to allocate mailbox buffer.");
2944 
2945 		return (1);
2946 	}
2947 
2948 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
2949 	    "SLI4: Updating parms...");
2950 
2951 	mb = (MAILBOX *)mbox;
2952 
2953 	old_prog_id = WakeUpParms->sli4_prog_id;
2954 	WakeUpParms->sli4_prog_id = *prog_id;
2955 
2956 	emlxs_format_update_parms(mbox, WakeUpParms);
2957 
2958 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
2959 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
2960 		    "Unable to update wakeup parameters. Mailbox cmd=%x "
2961 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
2962 
2963 		WakeUpParms->sli4_prog_id = old_prog_id;
2964 		rval = 1;
2965 	}
2966 
2967 	if (mbox) {
2968 		kmem_free(mbox, sizeof (MAILBOXQ));
2969 	}
2970 
2971 	return (rval);
2972 
2973 } /* emlxs_update_sli4_wakeup_parms() */
2974 
2975 
2976 static uint32_t
emlxs_clean_flash(emlxs_hba_t * hba,PWAKE_UP_PARMS OldWakeUpParms,PWAKE_UP_PARMS NewWakeUpParms)2977 emlxs_clean_flash(emlxs_hba_t *hba,
2978     PWAKE_UP_PARMS OldWakeUpParms, PWAKE_UP_PARMS NewWakeUpParms)
2979 {
2980 	emlxs_port_t *port = &PPORT;
2981 	PROG_ID load_list[MAX_LOAD_ENTRY];
2982 	PROG_ID *wakeup_list[MAX_LOAD_ENTRY];
2983 	uint32_t count;
2984 	uint32_t i;
2985 	uint32_t j;
2986 	uint32_t k = 0;
2987 	uint32_t *wptr;
2988 
2989 	if (!NewWakeUpParms) {
2990 		return (1);
2991 	}
2992 
2993 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
2994 	    "Cleaning flash...");
2995 
2996 	/* If old wakeup parameter list is available, */
2997 	/* then cleanup old entries */
2998 	if (OldWakeUpParms) {
2999 		if (bcmp(&OldWakeUpParms->prog_id, &NewWakeUpParms->prog_id,
3000 		    sizeof (PROG_ID))) {
3001 
3002 			wptr = (uint32_t *)&OldWakeUpParms->prog_id;
3003 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3004 			    "OLD:      prog_id: 0x%08x 0x%08x  Removing.",
3005 			    wptr[0], wptr[1]);
3006 
3007 			(void) emlxs_delete_load_entry(hba,
3008 			    &OldWakeUpParms->prog_id);
3009 		}
3010 
3011 		if (bcmp(&OldWakeUpParms->u0.boot_bios_id,
3012 		    &NewWakeUpParms->u0.boot_bios_id, sizeof (PROG_ID))) {
3013 
3014 			wptr = (uint32_t *)&OldWakeUpParms->u0.boot_bios_id;
3015 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3016 			    "OLD: boot_bios_id: 0x%08x 0x%08x  Removing.",
3017 			    wptr[0], wptr[1]);
3018 
3019 			(void) emlxs_delete_load_entry(hba,
3020 			    &OldWakeUpParms->u0.boot_bios_id);
3021 		}
3022 
3023 		if (bcmp(&OldWakeUpParms->sli1_prog_id,
3024 		    &NewWakeUpParms->sli1_prog_id, sizeof (PROG_ID))) {
3025 
3026 			wptr = (uint32_t *)&OldWakeUpParms->sli1_prog_id;
3027 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3028 			    "OLD: sli1_prog_id: 0x%08x 0x%08x  Removing.",
3029 			    wptr[0], wptr[1]);
3030 
3031 			(void) emlxs_delete_load_entry(hba,
3032 			    &OldWakeUpParms->sli1_prog_id);
3033 		}
3034 
3035 		if (bcmp(&OldWakeUpParms->sli2_prog_id,
3036 		    &NewWakeUpParms->sli2_prog_id, sizeof (PROG_ID))) {
3037 
3038 			wptr = (uint32_t *)&OldWakeUpParms->sli2_prog_id;
3039 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3040 			    "OLD: sli2_prog_id: 0x%08x 0x%08x  Removing.",
3041 			    wptr[0], wptr[1]);
3042 
3043 			(void) emlxs_delete_load_entry(hba,
3044 			    &OldWakeUpParms->sli2_prog_id);
3045 		}
3046 
3047 		if (bcmp(&OldWakeUpParms->sli3_prog_id,
3048 		    &NewWakeUpParms->sli3_prog_id, sizeof (PROG_ID))) {
3049 
3050 			wptr = (uint32_t *)&OldWakeUpParms->sli3_prog_id;
3051 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3052 			    "OLD: sli3_prog_id: 0x%08x 0x%08x  Removing.",
3053 			    wptr[0], wptr[1]);
3054 
3055 			(void) emlxs_delete_load_entry(hba,
3056 			    &OldWakeUpParms->sli3_prog_id);
3057 		}
3058 
3059 		if (bcmp(&OldWakeUpParms->sli4_prog_id,
3060 		    &NewWakeUpParms->sli4_prog_id, sizeof (PROG_ID))) {
3061 
3062 			wptr = (uint32_t *)&OldWakeUpParms->sli4_prog_id;
3063 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3064 			    "OLD: sli4_prog_id: 0x%08x 0x%08x  Removing.",
3065 			    wptr[0], wptr[1]);
3066 
3067 			(void) emlxs_delete_load_entry(hba,
3068 			    &OldWakeUpParms->sli4_prog_id);
3069 		}
3070 
3071 		return (0);
3072 	}
3073 
3074 	/* Otherwise use the current load list */
3075 	count = emlxs_get_load_list(hba, load_list);
3076 
3077 	if (!count) {
3078 		return (1);
3079 	}
3080 
3081 	/* Init the wakeup list */
3082 	wptr = (uint32_t *)&NewWakeUpParms->prog_id;
3083 	if (*wptr) {
3084 		wakeup_list[k++] = &NewWakeUpParms->prog_id;
3085 	}
3086 
3087 	wptr = (uint32_t *)&NewWakeUpParms->u0.boot_bios_id;
3088 	if (*wptr) {
3089 		wakeup_list[k++] = &NewWakeUpParms->u0.boot_bios_id;
3090 	}
3091 
3092 	wptr = (uint32_t *)&NewWakeUpParms->sli1_prog_id;
3093 	if (*wptr) {
3094 		wakeup_list[k++] = &NewWakeUpParms->sli1_prog_id;
3095 	}
3096 
3097 	wptr = (uint32_t *)&NewWakeUpParms->sli2_prog_id;
3098 	if (*wptr) {
3099 		wakeup_list[k++] = &NewWakeUpParms->sli2_prog_id;
3100 	}
3101 
3102 	wptr = (uint32_t *)&NewWakeUpParms->sli3_prog_id;
3103 	if (*wptr) {
3104 		wakeup_list[k++] = &NewWakeUpParms->sli3_prog_id;
3105 	}
3106 
3107 	wptr = (uint32_t *)&NewWakeUpParms->sli4_prog_id;
3108 	if (*wptr) {
3109 		wakeup_list[k++] = &NewWakeUpParms->sli4_prog_id;
3110 	}
3111 
3112 	if (k == 0) {
3113 		return (0);
3114 	}
3115 
3116 	/* Match load list to wakeup list */
3117 	for (i = 0; i < count; i++) {
3118 
3119 		wptr = (uint32_t *)&load_list[i];
3120 
3121 		for (j = 0; j < k; j++) {
3122 			if (bcmp((uint8_t *)wakeup_list[j],
3123 			    (uint8_t *)&load_list[i], sizeof (PROG_ID)) == 0) {
3124 				break;
3125 			}
3126 		}
3127 
3128 		/* No match */
3129 		if (j == k) {
3130 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3131 			    "Load List[%d]: %08x %08x  Removing.",
3132 			    i, wptr[0], wptr[1]);
3133 
3134 			(void) emlxs_delete_load_entry(hba, &load_list[i]);
3135 		} else {
3136 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3137 			    "Load List[%d]: %08x %08x  Preserving.",
3138 			    i, wptr[0], wptr[1]);
3139 		}
3140 	}
3141 
3142 	return (0);
3143 
3144 } /* emlxs_clean_flash() */
3145 
3146 
3147 /* ARGSUSED */
3148 static uint32_t
emlxs_start_rel_download(emlxs_hba_t * hba,PIMAGE_HDR ImageHdr,caddr_t Buffer,PWAKE_UP_PARMS WakeUpParms,uint32_t dwc_flag)3149 emlxs_start_rel_download(emlxs_hba_t *hba,
3150     PIMAGE_HDR ImageHdr,
3151     caddr_t Buffer,
3152     PWAKE_UP_PARMS WakeUpParms,
3153     uint32_t dwc_flag)
3154 {
3155 	emlxs_port_t *port = &PPORT;
3156 	MAILBOXQ *mbox;
3157 	MAILBOX *mb;
3158 	uint32_t *Src;
3159 	uint32_t *Dst;
3160 	caddr_t DataBuffer = NULL;
3161 	uint32_t rval = 0;
3162 	uint32_t DlByteCount;
3163 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
3164 	uint32_t DlCount;
3165 	uint32_t i;
3166 	uint32_t *wptr;
3167 
3168 	wptr = (uint32_t *)&ImageHdr->Id;
3169 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
3170 	    "Relative download: %08x %08x", wptr[0], wptr[1]);
3171 
3172 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
3173 	    KM_NOSLEEP)) == NULL) {
3174 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3175 		    "Unable to allocate data buffer.");
3176 
3177 		return (1);
3178 	}
3179 
3180 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3181 	    KM_NOSLEEP)) == NULL) {
3182 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3183 		    "Unable to allocate mailbox buffer.");
3184 
3185 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3186 
3187 		return (1);
3188 	}
3189 
3190 	mb = (MAILBOX *)mbox;
3191 
3192 	DlByteCount = ImageHdr->BlockSize;
3193 
3194 	emlxs_format_prog_flash(mbox, 0, DlByteCount, ERASE_FLASH, 0, 0, 0,
3195 	    &ImageHdr->Id, 0);
3196 
3197 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
3198 	    "  Erasing flash...");
3199 
3200 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
3201 
3202 	if (rval) {
3203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3204 		    "Unable to erase flash. Mailbox cmd=%x status=%x",
3205 		    mb->mbxCommand, mb->mbxStatus);
3206 
3207 		goto EXIT_REL_DOWNLOAD;
3208 	}
3209 
3210 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
3211 	    "  Programming flash...");
3212 
3213 	while (DlByteCount) {
3214 		if (DlByteCount > SegSize) {
3215 			DlCount = SegSize;
3216 		} else {
3217 			DlCount = DlByteCount;
3218 		}
3219 		DlByteCount -= DlCount;
3220 
3221 		Dst = (uint32_t *)DataBuffer;
3222 		Src = (uint32_t *)Buffer;
3223 
3224 		for (i = 0; i < (DlCount / 4); i++) {
3225 			*Dst = *Src;
3226 			Dst++;
3227 			Src++;
3228 		}
3229 
3230 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
3231 		    (volatile uint32_t *)
3232 		    ((volatile char *)hba->sli.sli3.slim_addr +
3233 		    sizeof (MAILBOX)), (DlCount / sizeof (uint32_t)));
3234 
3235 		emlxs_format_prog_flash(mbox,
3236 		    0,
3237 		    DlCount,
3238 		    PROGRAM_FLASH,
3239 		    (DlByteCount) ? 0 : 1,
3240 		    0, DlCount, &ImageHdr->Id, dwc_flag);
3241 
3242 		rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0);
3243 
3244 		if (rval) {
3245 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3246 			    "Unable to program flash. Mailbox cmd=%x status=%x",
3247 			    mb->mbxCommand, mb->mbxStatus);
3248 
3249 			goto EXIT_REL_DOWNLOAD;
3250 		}
3251 
3252 		Buffer += DlCount;
3253 	}
3254 
3255 #ifdef FMA_SUPPORT
3256 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
3257 	    != DDI_FM_OK) {
3258 		EMLXS_MSGF(EMLXS_CONTEXT,
3259 		    &emlxs_invalid_access_handle_msg, NULL);
3260 
3261 		rval = 1;
3262 
3263 		goto EXIT_REL_DOWNLOAD;
3264 	}
3265 #endif  /* FMA_SUPPORT */
3266 
3267 	/* Update wakeup parameters */
3268 	switch (ImageHdr->Id.Type) {
3269 	case TEST_PROGRAM:
3270 		break;
3271 
3272 	case FUNC_FIRMWARE:
3273 		if (!dwc_flag) {
3274 			rval = emlxs_update_ff_wakeup_parms(hba, WakeUpParms,
3275 			    &ImageHdr->Id);
3276 		} else {
3277 			WakeUpParms->prog_id = ImageHdr->Id;
3278 		}
3279 		break;
3280 
3281 	case BOOT_BIOS:
3282 		if (!dwc_flag) {
3283 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
3284 			    "BOOT: Updating parms...");
3285 
3286 			rval = emlxs_update_boot_wakeup_parms(hba, WakeUpParms,
3287 			    &ImageHdr->Id, 1);
3288 		} else {
3289 			if (hba->wakeup_parms.u0.boot_bios_wd[0]) {
3290 				WakeUpParms->u0.boot_bios_id = ImageHdr->Id;
3291 			}
3292 
3293 			if (!(hba->model_info.chip &
3294 			    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
3295 				WakeUpParms->u1.EROM_prog_id = ImageHdr->Id;
3296 			}
3297 		}
3298 		break;
3299 
3300 	case SLI1_OVERLAY:
3301 		if (!dwc_flag) {
3302 			rval = emlxs_update_sli1_wakeup_parms(hba, WakeUpParms,
3303 			    &ImageHdr->Id);
3304 		} else {
3305 			WakeUpParms->sli1_prog_id = ImageHdr->Id;
3306 		}
3307 		break;
3308 
3309 	case SLI2_OVERLAY:
3310 		if (!dwc_flag) {
3311 			rval = emlxs_update_sli2_wakeup_parms(hba, WakeUpParms,
3312 			    &ImageHdr->Id);
3313 		} else {
3314 			WakeUpParms->sli2_prog_id = ImageHdr->Id;
3315 		}
3316 		break;
3317 
3318 	case SLI3_OVERLAY:
3319 		if (!dwc_flag) {
3320 			rval = emlxs_update_sli3_wakeup_parms(hba, WakeUpParms,
3321 			    &ImageHdr->Id);
3322 		} else {
3323 			WakeUpParms->sli3_prog_id = ImageHdr->Id;
3324 		}
3325 		break;
3326 
3327 	case SLI4_OVERLAY:
3328 		if (!dwc_flag) {
3329 			rval = emlxs_update_sli4_wakeup_parms(hba, WakeUpParms,
3330 			    &ImageHdr->Id);
3331 		} else {
3332 			WakeUpParms->sli4_prog_id = ImageHdr->Id;
3333 		}
3334 		break;
3335 
3336 	default:
3337 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
3338 		    "Image type not supported. Type=%x", ImageHdr->Id.Type);
3339 
3340 		break;
3341 	}
3342 
3343 EXIT_REL_DOWNLOAD:
3344 	if (DataBuffer) {
3345 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
3346 	}
3347 
3348 	if (mbox) {
3349 		kmem_free(mbox, sizeof (MAILBOXQ));
3350 	}
3351 
3352 	return (rval);
3353 
3354 } /* emlxs_start_rel_download() */
3355 
3356 
3357 static uint32_t
emlxs_proc_rel_2mb(emlxs_hba_t * hba,caddr_t buffer,emlxs_fw_image_t * fw_image)3358 emlxs_proc_rel_2mb(emlxs_hba_t *hba, caddr_t buffer, emlxs_fw_image_t *fw_image)
3359 {
3360 	emlxs_port_t *port = &PPORT;
3361 	uint32_t rval = 0;
3362 	WAKE_UP_PARMS RelWakeUpParms;
3363 	WAKE_UP_PARMS WakeUpParms;
3364 	uint32_t i;
3365 	IMAGE_HDR ImageHdr;
3366 	caddr_t bptr;
3367 	uint32_t flash_cleaned = 0;
3368 
3369 	if (emlxs_read_wakeup_parms(hba, &WakeUpParms, 0)) {
3370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3371 		    "Unable to get wakeup parameters.");
3372 
3373 		return (EMLXS_IMAGE_FAILED);
3374 	}
3375 
3376 download:
3377 
3378 	bcopy(&WakeUpParms, &RelWakeUpParms, sizeof (WAKE_UP_PARMS));
3379 
3380 	for (i = 0; i < MAX_PROG_TYPES; i++) {
3381 		if (!fw_image->prog[i].version) {
3382 			continue;
3383 		}
3384 
3385 		bptr = buffer + fw_image->prog[i].offset;
3386 
3387 		bcopy(bptr, &ImageHdr, sizeof (IMAGE_HDR));
3388 
3389 		rval = emlxs_start_rel_download(hba, &ImageHdr, bptr,
3390 		    &RelWakeUpParms, 1);
3391 
3392 		if (rval) {
3393 			EMLXS_MSGF(EMLXS_CONTEXT,
3394 			    &emlxs_download_failed_msg,
3395 			    "Failed to program flash.");
3396 
3397 			if ((rval == NO_FLASH_MEM_AVAIL) && !flash_cleaned) {
3398 				/* Cleanup using current load list */
3399 				(void) emlxs_clean_flash(hba, 0, &WakeUpParms);
3400 
3401 				flash_cleaned = 1;
3402 				goto download;
3403 			}
3404 
3405 			return (EMLXS_IMAGE_FAILED);
3406 		}
3407 	}
3408 
3409 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_detail_msg,
3410 	    "Updating wakeup parameters.");
3411 
3412 	if (emlxs_update_wakeup_parms(hba, &RelWakeUpParms,
3413 	    &RelWakeUpParms)) {
3414 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3415 		    "Unable to update parameters.");
3416 
3417 		return (EMLXS_IMAGE_FAILED);
3418 	}
3419 
3420 	/* Cleanup using old wakeup paramters */
3421 	(void) emlxs_clean_flash(hba, &WakeUpParms, &RelWakeUpParms);
3422 
3423 	return (0);
3424 
3425 } /* emlxs_proc_rel_2mb() */
3426 
3427 
3428 #define	FLASH_POLLING_BIT	0x80
3429 #define	FLASH_ERROR_BIT		0x20
3430 
3431 typedef struct _flash_t
3432 {
3433 	uint32_t	offset;
3434 	uint8_t		val;
3435 } flash_t;
3436 
3437 
3438 
3439 static uint32_t
emlxs_write_fcode_flash(emlxs_hba_t * hba,PIMAGE_HDR ImageHdr,caddr_t Buffer)3440 emlxs_write_fcode_flash(emlxs_hba_t *hba,
3441     PIMAGE_HDR ImageHdr, caddr_t Buffer)
3442 {
3443 	emlxs_port_t *port = &PPORT;
3444 	uint8_t bb;
3445 	uint8_t cc;
3446 	uint8_t *src;
3447 	uint32_t DlByteCount = ImageHdr->BlockSize;
3448 	uint32_t i;
3449 	uint32_t j;
3450 	uint32_t k;
3451 
3452 	flash_t wr[3] = {
3453 		{0x555, 0xaa},
3454 		{0x2aa, 0x55},
3455 		{0x555, 0xa0}
3456 	};
3457 
3458 	/* Load Fcode */
3459 	src = (uint8_t *)Buffer + sizeof (IMAGE_HDR);
3460 	for (i = 0; i < DlByteCount; i++) {
3461 		for (k = 0; k < 3; k++) {
3462 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3463 		}
3464 
3465 		/* Reverse Endian word alignment */
3466 		j = (i & 3) ^ 3;
3467 
3468 		bb = src[j];
3469 
3470 		if (j == 0) {
3471 			src += 4;
3472 		}
3473 
3474 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3475 
3476 		/* check for complete */
3477 		for (;;) {
3478 			BUSYWAIT_US(20);
3479 
3480 			cc = SBUS_READ_FLASH_COPY(hba, i);
3481 
3482 			/* If data matches then continue */
3483 			if (cc == bb) {
3484 				break;
3485 			}
3486 
3487 			/* Polling bit will be inverse final value */
3488 			/* while active */
3489 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3490 				/* Still busy */
3491 
3492 				/* Check for error bit */
3493 				if (cc & FLASH_ERROR_BIT) {
3494 					/* Read data one more time */
3495 					cc = SBUS_READ_FLASH_COPY(hba, i);
3496 
3497 					/* Check if data matches */
3498 					if (cc == bb) {
3499 						break;
3500 					}
3501 
3502 					EMLXS_MSGF(EMLXS_CONTEXT,
3503 					    &emlxs_download_failed_msg,
3504 					    "FCode write error: offset:%x "
3505 					    "wrote:%x read:%x\n", i, bb, cc);
3506 
3507 					return (1);
3508 				}
3509 			}
3510 		}
3511 	}
3512 
3513 	/* Load Header */
3514 	src = (uint8_t *)ImageHdr;
3515 
3516 	for (i = (0xFFFF - sizeof (IMAGE_HDR)); i < 0xFFFF; i++) {
3517 		for (k = 0; k < 3; k++) {
3518 			SBUS_WRITE_FLASH_COPY(hba, wr[k].offset, wr[k].val);
3519 		}
3520 
3521 		/* Reverse Endian word alignment */
3522 		j = (i & 3) ^ 3;
3523 
3524 		bb = src[j];
3525 
3526 		if (j == 0) {
3527 			src += 4;
3528 		}
3529 
3530 		SBUS_WRITE_FLASH_COPY(hba, i, bb);
3531 
3532 		/* check for complete */
3533 		for (;;) {
3534 			BUSYWAIT_US(20);
3535 
3536 			cc = SBUS_READ_FLASH_COPY(hba, i);
3537 
3538 			/* If data matches then continue */
3539 			if (cc == bb) {
3540 				break;
3541 			}
3542 
3543 			/* Polling bit will be inverse final value */
3544 			/* while active */
3545 			if ((cc ^ bb) & FLASH_POLLING_BIT) {
3546 				/* Still busy */
3547 
3548 				/* Check for error bit */
3549 				if (cc & FLASH_ERROR_BIT) {
3550 					/* Read data one more time */
3551 					cc = SBUS_READ_FLASH_COPY(hba, i);
3552 
3553 					/* Check if data matches */
3554 					if (cc == bb) {
3555 						break;
3556 					}
3557 
3558 					EMLXS_MSGF(EMLXS_CONTEXT,
3559 					    &emlxs_download_failed_msg,
3560 					    "FCode write error: offset:%x "
3561 					    "wrote:%x read:%x\n", i, bb, cc);
3562 
3563 					return (1);
3564 				}
3565 			}
3566 		}
3567 	}
3568 
3569 #ifdef FMA_SUPPORT
3570 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3571 	    != DDI_FM_OK) {
3572 		EMLXS_MSGF(EMLXS_CONTEXT,
3573 		    &emlxs_invalid_access_handle_msg, NULL);
3574 		return (1);
3575 	}
3576 #endif  /* FMA_SUPPORT */
3577 
3578 	return (0);
3579 
3580 } /* emlxs_write_fcode_flash() */
3581 
3582 
3583 
3584 static uint32_t
emlxs_erase_fcode_flash(emlxs_hba_t * hba)3585 emlxs_erase_fcode_flash(emlxs_hba_t *hba)
3586 {
3587 	emlxs_port_t *port = &PPORT;
3588 	int32_t i, j;
3589 	uint8_t cc;
3590 	uint32_t offset;
3591 
3592 	flash_t ef[6] = {
3593 		{0x555, 0xaa},
3594 		{0x2aa, 0x55},
3595 		{0x555, 0x80},
3596 		{0x555, 0xaa},
3597 		{0x2aa, 0x55},
3598 		{0x555, 0x10}
3599 	};
3600 
3601 	/* Auto select */
3602 	flash_t as[3] = {
3603 		{0x555, 0xaa},
3604 		{0x2aa, 0x55},
3605 		{0x555, 0x90}
3606 	};
3607 
3608 
3609 	/* Check Manufacturers Code */
3610 	for (i = 0; i < 3; i++) {
3611 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3612 	}
3613 
3614 	cc = SBUS_READ_FLASH_COPY(hba, 0);
3615 
3616 	/* Check Device Code */
3617 	for (i = 0; i < 3; i++) {
3618 		SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3619 	}
3620 
3621 	cc = SBUS_READ_FLASH_COPY(hba, 1);
3622 
3623 
3624 	/* Check block protections (up to 4 16K blocks = 64K) */
3625 	for (j = 0; j < 4; j++) {
3626 		for (i = 0; i < 3; i++) {
3627 			SBUS_WRITE_FLASH_COPY(hba, as[i].offset, as[i].val);
3628 		}
3629 
3630 		offset = (j << 14) | 0x2;
3631 
3632 		cc = SBUS_READ_FLASH_COPY(hba, offset);
3633 
3634 		if (cc == 0x01) {
3635 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
3636 			    "Block %d is protected and can't be erased.", j);
3637 		}
3638 	}
3639 
3640 	/* Write erase flash sequence */
3641 	for (i = 0; i < 6; i++) {
3642 		SBUS_WRITE_FLASH_COPY(hba, ef[i].offset, ef[i].val);
3643 	}
3644 
3645 	/* check for complete */
3646 	for (;;) {
3647 		/* Delay 3 seconds */
3648 		BUSYWAIT_MS(3000);
3649 
3650 		cc = SBUS_READ_FLASH_COPY(hba, 0);
3651 
3652 
3653 		/* If data matches then continue; */
3654 		if (cc == 0xff) {
3655 			break;
3656 		}
3657 
3658 		/* Polling bit will be inverse final value while active */
3659 		if ((cc ^ 0xff) & FLASH_POLLING_BIT) {
3660 			/* Still busy */
3661 
3662 			/* Check for error bit */
3663 			if (cc & FLASH_ERROR_BIT) {
3664 				/* Read data one more time */
3665 				cc = SBUS_READ_FLASH_COPY(hba, 0);
3666 
3667 				/* Check if data matches */
3668 				if (cc == 0xff) {
3669 					break;
3670 				}
3671 
3672 				EMLXS_MSGF(EMLXS_CONTEXT,
3673 				    &emlxs_download_failed_msg,
3674 				    "FCode write error: offset:%x wrote:%x "
3675 				    "read:%x\n", i, 0xff, cc);
3676 
3677 				return (1);
3678 			}
3679 		}
3680 	}
3681 
3682 #ifdef FMA_SUPPORT
3683 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
3684 	    != DDI_FM_OK) {
3685 		EMLXS_MSGF(EMLXS_CONTEXT,
3686 		    &emlxs_invalid_access_handle_msg, NULL);
3687 		return (1);
3688 	}
3689 #endif  /* FMA_SUPPORT */
3690 
3691 	return (0);
3692 
3693 } /* emlxs_erase_fcode_flash() */
3694 
3695 
3696 static uint32_t
emlxs_delete_load_entry(emlxs_hba_t * hba,PROG_ID * progId)3697 emlxs_delete_load_entry(emlxs_hba_t *hba, PROG_ID *progId)
3698 {
3699 	emlxs_port_t *port = &PPORT;
3700 	MAILBOXQ *mbox = NULL;
3701 	MAILBOX *mb;
3702 	uint32_t rval = 0;
3703 
3704 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3705 	    KM_NOSLEEP)) == NULL) {
3706 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3707 		    "Unable to allocate mailbox buffer.");
3708 
3709 		return (1);
3710 	}
3711 
3712 	mb = (MAILBOX *)mbox;
3713 	mb->mbxCommand = MBX_DEL_LD_ENTRY;
3714 	mb->un.varDelLdEntry.list_req = FLASH_LOAD_LIST;
3715 	mb->un.varDelLdEntry.prog_id = *progId;
3716 
3717 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3718 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3719 		    "Unable to delete load entry: Mailbox cmd=%x status=%x",
3720 		    mb->mbxCommand, mb->mbxStatus);
3721 
3722 		rval = 1;
3723 	}
3724 
3725 done:
3726 
3727 	if (mbox) {
3728 		kmem_free(mbox, sizeof (MAILBOXQ));
3729 	}
3730 
3731 	return (rval);
3732 
3733 } /* emlxs_delete_load_entry() */
3734 
3735 
3736 extern uint32_t
emlxs_get_load_list(emlxs_hba_t * hba,PROG_ID * load_list)3737 emlxs_get_load_list(emlxs_hba_t *hba, PROG_ID *load_list)
3738 {
3739 	emlxs_port_t *port = &PPORT;
3740 	LOAD_ENTRY *LoadEntry;
3741 	LOAD_LIST *LoadList = NULL;
3742 	uint32_t i;
3743 	uint32_t count = 0;
3744 
3745 	bzero(load_list, (sizeof (PROG_ID) * MAX_LOAD_ENTRY));
3746 
3747 	if ((LoadList = (LOAD_LIST *)kmem_zalloc(sizeof (LOAD_LIST),
3748 	    KM_NOSLEEP)) == NULL) {
3749 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3750 		    "Unable to allocate LOADLIST buffer.");
3751 
3752 		goto done;
3753 	}
3754 
3755 	if (emlxs_read_load_list(hba, LoadList)) {
3756 		goto done;
3757 	}
3758 
3759 	for (i = 0; i < LoadList->entry_cnt; i++) {
3760 		LoadEntry = &LoadList->load_entry[i];
3761 		if ((LoadEntry->un.wd[0] != 0) &&
3762 		    (LoadEntry->un.wd[0] != 0xffffffff)) {
3763 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3764 			    "Load List[%d]: %08x %08x", count,
3765 			    LoadEntry->un.wd[0], LoadEntry->un.wd[1]);
3766 
3767 			load_list[count++] = LoadEntry->un.id;
3768 		}
3769 	}
3770 
3771 done:
3772 
3773 	if (LoadList) {
3774 		kmem_free(LoadList, sizeof (LOAD_LIST));
3775 	}
3776 
3777 	return (count);
3778 
3779 } /* emlxs_get_load_list() */
3780 
3781 
3782 extern uint32_t
emlxs_read_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms,uint32_t verbose)3783 emlxs_read_wakeup_parms(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms,
3784     uint32_t verbose)
3785 {
3786 	emlxs_port_t *port = &PPORT;
3787 	MAILBOXQ *mbox;
3788 	MAILBOX *mb;
3789 	uint32_t rval = 0;
3790 	uint32_t *wd;
3791 
3792 	bzero(WakeUpParms, sizeof (WAKE_UP_PARMS));
3793 
3794 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3795 	    KM_NOSLEEP)) == NULL) {
3796 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3797 		    "Unable to allocate mailbox buffer.");
3798 
3799 		return (1);
3800 	}
3801 
3802 	mb = (MAILBOX *)mbox;
3803 
3804 	emlxs_format_dump(hba, mbox,
3805 	    DMP_NV_PARAMS,
3806 	    WAKE_UP_PARMS_REGION_ID,
3807 	    sizeof (WAKE_UP_PARMS) / sizeof (uint32_t), 0);
3808 
3809 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3810 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3811 		    "Unable to get parameters: Mailbox cmd=%x status=%x",
3812 		    mb->mbxCommand, mb->mbxStatus);
3813 
3814 		if (mb->un.varDmp.word_cnt == (uint32_t)CFG_DATA_NO_REGION) {
3815 			rval = (uint32_t)CFG_DATA_NO_REGION;
3816 		} else {
3817 			rval = 1;
3818 		}
3819 	} else {
3820 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3821 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3822 			    0, hba->sli.sli4.dump_region.size,
3823 			    DDI_DMA_SYNC_FORKERNEL);
3824 
3825 			bcopy((caddr_t)hba->sli.sli4.dump_region.virt,
3826 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3827 		} else {
3828 			bcopy((caddr_t)&mb->un.varDmp.resp_offset,
3829 			    (caddr_t)WakeUpParms, sizeof (WAKE_UP_PARMS));
3830 		}
3831 
3832 		if (verbose) {
3833 			wd = (uint32_t *)&WakeUpParms->prog_id;
3834 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3835 			    "Wakeup:      prog_id=%08x %08x", wd[0], wd[1]);
3836 
3837 			wd = (uint32_t *)&WakeUpParms->u0.boot_bios_id;
3838 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3839 			    "Wakeup: boot_bios_id=%08x %08x", wd[0], wd[1]);
3840 
3841 			wd = (uint32_t *)&WakeUpParms->sli1_prog_id;
3842 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3843 			    "Wakeup: sli1_prog_id=%08x %08x", wd[0], wd[1]);
3844 
3845 			wd = (uint32_t *)&WakeUpParms->sli2_prog_id;
3846 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3847 			    "Wakeup: sli2_prog_id=%08x %08x", wd[0], wd[1]);
3848 
3849 			wd = (uint32_t *)&WakeUpParms->sli3_prog_id;
3850 			if (wd[0] || wd[1]) {
3851 				EMLXS_MSGF(EMLXS_CONTEXT,
3852 				    &emlxs_init_debug_msg,
3853 				    "Wakeup: sli3_prog_id=%08x %08x", wd[0],
3854 				    wd[1]);
3855 			}
3856 
3857 			wd = (uint32_t *)&WakeUpParms->sli4_prog_id;
3858 			if (wd[0] || wd[1]) {
3859 				EMLXS_MSGF(EMLXS_CONTEXT,
3860 				    &emlxs_init_debug_msg,
3861 				    "Wakeup: sli4_prog_id=%08x %08x", wd[0],
3862 				    wd[1]);
3863 			}
3864 
3865 			wd = (uint32_t *)&WakeUpParms->u1.EROM_prog_id;
3866 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3867 			    "Wakeup: EROM_prog_id=%08x %08x", wd[0], wd[1]);
3868 
3869 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3870 			    "Wakeup: pci_cfg_rsvd=%x",
3871 			    WakeUpParms->pci_cfg_rsvd);
3872 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3873 			    "Wakeup:  use_hdw_def=%x",
3874 			    WakeUpParms->use_hdw_def);
3875 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3876 			    "Wakeup:  pci_cfg_sel=%x",
3877 			    WakeUpParms->pci_cfg_sel);
3878 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
3879 			    "Wakeup:   cfg_lookup=%x",
3880 			    WakeUpParms->pci_cfg_lookup_sel);
3881 		}
3882 	}
3883 
3884 done:
3885 
3886 	if (mbox) {
3887 		kmem_free(mbox, sizeof (MAILBOXQ));
3888 	}
3889 
3890 #ifdef FMA_SUPPORT
3891 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3892 		if (emlxs_fm_check_dma_handle(hba,
3893 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
3894 			EMLXS_MSGF(EMLXS_CONTEXT,
3895 			    &emlxs_invalid_dma_handle_msg,
3896 			    "read_wakeup_parms: hdl=%p",
3897 			    hba->sli.sli4.dump_region.dma_handle);
3898 			rval = 1;
3899 		}
3900 	}
3901 #endif  /* FMA_SUPPORT */
3902 
3903 	return (rval);
3904 
3905 } /* emlxs_read_wakeup_parms() */
3906 
3907 
3908 static uint32_t
emlxs_read_load_list(emlxs_hba_t * hba,LOAD_LIST * LoadList)3909 emlxs_read_load_list(emlxs_hba_t *hba, LOAD_LIST *LoadList)
3910 {
3911 	emlxs_port_t *port = &PPORT;
3912 	LOAD_ENTRY *LoadEntry;
3913 	uint32_t *Uptr;
3914 	uint32_t CurEntryAddr;
3915 	MAILBOXQ *mbox = NULL;
3916 	MAILBOX *mb;
3917 
3918 	bzero((caddr_t)LoadList, sizeof (LOAD_LIST));
3919 
3920 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
3921 	    KM_NOSLEEP)) == NULL) {
3922 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3923 		    "Unable to allocate mailbox buffer.");
3924 
3925 		return (1);
3926 	}
3927 
3928 	mb = (MAILBOX *)mbox;
3929 
3930 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, FLASH_LOAD_LIST_ADR);
3931 
3932 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
3933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3934 		    "Unable to get load list: Mailbox cmd=%x status=%x",
3935 		    mb->mbxCommand, mb->mbxStatus);
3936 
3937 		goto done;
3938 	}
3939 
3940 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3941 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
3942 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
3943 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3944 	} else {
3945 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3946 	}
3947 
3948 	LoadList->head = Uptr[0];
3949 	LoadList->tail = Uptr[1];
3950 
3951 	CurEntryAddr = LoadList->head;
3952 
3953 	while ((CurEntryAddr != FLASH_LOAD_LIST_ADR) &&
3954 	    (LoadList->entry_cnt < MAX_LOAD_ENTRY)) {
3955 		LoadEntry = &LoadList->load_entry[LoadList->entry_cnt];
3956 		LoadList->entry_cnt++;
3957 
3958 		emlxs_format_dump(hba, mbox,
3959 		    DMP_MEM_REG, 0, FLASH_LOAD_ENTRY_SIZE, CurEntryAddr);
3960 
3961 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
3962 		    MBX_SUCCESS) {
3963 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
3964 			    "Unable to get load list (%d): Mailbox cmd=%x "
3965 			    "status=%x", LoadList->entry_cnt, mb->mbxCommand,
3966 			    mb->mbxStatus);
3967 
3968 			goto done;
3969 		}
3970 
3971 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3972 			EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle,
3973 			    0, hba->sli.sli4.dump_region.size,
3974 			    DDI_DMA_SYNC_FORKERNEL);
3975 			Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
3976 		} else {
3977 			Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
3978 		}
3979 
3980 		LoadEntry->next = Uptr[0];
3981 		LoadEntry->prev = Uptr[1];
3982 		LoadEntry->start_adr = Uptr[2];
3983 		LoadEntry->len = Uptr[3];
3984 		LoadEntry->un.wd[0] = Uptr[4];
3985 		LoadEntry->un.wd[1] = Uptr[5];
3986 
3987 		/* update next current load entry address */
3988 		CurEntryAddr = LoadEntry->next;
3989 
3990 	}	/* end of while (not end of list) */
3991 
3992 done:
3993 
3994 	if (mbox) {
3995 		kmem_free(mbox, sizeof (MAILBOXQ));
3996 	}
3997 
3998 #ifdef FMA_SUPPORT
3999 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
4000 		if (emlxs_fm_check_dma_handle(hba,
4001 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
4002 			EMLXS_MSGF(EMLXS_CONTEXT,
4003 			    &emlxs_invalid_dma_handle_msg,
4004 			    "read_load_list: hdl=%p",
4005 			    hba->sli.sli4.dump_region.dma_handle);
4006 			return (1);
4007 		}
4008 	}
4009 #endif  /* FMA_SUPPORT */
4010 
4011 	return (0);
4012 
4013 } /* emlxs_read_load_list() */
4014 
4015 
4016 extern uint32_t
emlxs_get_boot_config(emlxs_hba_t * hba,uint8_t * boot_state)4017 emlxs_get_boot_config(emlxs_hba_t *hba, uint8_t *boot_state)
4018 {
4019 	emlxs_port_t *port = &PPORT;
4020 	MAILBOXQ *mbq;
4021 	MAILBOX4 *mb;
4022 	mbox_req_hdr_t	*hdr_req;
4023 	IOCTL_COMMON_BOOT_CFG *boot_cfg;
4024 
4025 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4026 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4027 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
4028 
4029 		return (1);
4030 	}
4031 
4032 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4033 	    KM_NOSLEEP)) == NULL) {
4034 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4035 		    "Unable to allocate mailbox buffer.");
4036 
4037 		return (1);
4038 	}
4039 
4040 	mb = (MAILBOX4 *)mbq;
4041 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
4042 
4043 	mb->un.varSLIConfig.be.embedded = 1;
4044 	mbq->nonembed = NULL;
4045 	mbq->mbox_cmpl = NULL;
4046 
4047 	mb->mbxCommand = MBX_SLI_CONFIG;
4048 	mb->mbxOwner = OWN_HOST;
4049 
4050 	hdr_req = (mbox_req_hdr_t *)
4051 	    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
4052 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
4053 	hdr_req->opcode = COMMON_OPCODE_GET_BOOT_CFG;
4054 
4055 	boot_cfg = (IOCTL_COMMON_BOOT_CFG *)(hdr_req + 1);
4056 
4057 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
4058 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4059 		    "Unable to read boot config: Mailbox cmd=%x "
4060 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4061 
4062 		kmem_free(mbq, sizeof (MAILBOXQ));
4063 		return (1);
4064 	}
4065 
4066 	*boot_state = boot_cfg->params.response.boot_status;
4067 
4068 	kmem_free(mbq, sizeof (MAILBOXQ));
4069 	return (0);
4070 }
4071 
4072 
4073 extern uint32_t
emlxs_set_boot_config(emlxs_hba_t * hba,uint8_t boot_state)4074 emlxs_set_boot_config(emlxs_hba_t *hba, uint8_t boot_state)
4075 {
4076 	emlxs_port_t *port = &PPORT;
4077 	MAILBOXQ *mbq;
4078 	MAILBOX4 *mb;
4079 	mbox_req_hdr_t	*hdr_req;
4080 	IOCTL_COMMON_BOOT_CFG *boot_cfg;
4081 
4082 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
4083 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4084 		    "Invalid sli_mode. mode=%d", hba->sli_mode);
4085 
4086 		return (1);
4087 	}
4088 
4089 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4090 	    KM_NOSLEEP)) == NULL) {
4091 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4092 		    "Unable to allocate mailbox buffer.");
4093 
4094 		return (1);
4095 	}
4096 
4097 	mb = (MAILBOX4 *)mbq;
4098 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
4099 
4100 	mb->un.varSLIConfig.be.embedded = 1;
4101 	mbq->nonembed = NULL;
4102 	mbq->mbox_cmpl = NULL;
4103 
4104 	mb->mbxCommand = MBX_SLI_CONFIG;
4105 	mb->mbxOwner = OWN_HOST;
4106 
4107 	hdr_req = (mbox_req_hdr_t *)
4108 	    &mb->un.varSLIConfig.be.un_hdr.hdr_req;
4109 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
4110 	hdr_req->opcode = COMMON_OPCODE_SET_BOOT_CFG;
4111 
4112 	boot_cfg = (IOCTL_COMMON_BOOT_CFG *)(hdr_req + 1);
4113 	boot_cfg->params.request.boot_status = boot_state;
4114 
4115 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0) != MBX_SUCCESS) {
4116 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
4117 		    "Unable to read boot config: Mailbox cmd=%x "
4118 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4119 
4120 		kmem_free(mbq, sizeof (MAILBOXQ));
4121 		return (1);
4122 	}
4123 
4124 	kmem_free(mbq, sizeof (MAILBOXQ));
4125 	return (0);
4126 }
4127 
4128 
4129 
4130 
4131 static int
emlxs_build_parms(caddr_t Buffer,PWAKE_UP_PARMS AbsWakeUpParms,uint32_t BufferSize,PAIF_HDR AifHeader)4132 emlxs_build_parms(caddr_t Buffer,
4133     PWAKE_UP_PARMS AbsWakeUpParms,
4134     uint32_t BufferSize, PAIF_HDR AifHeader)
4135 {
4136 	IMAGE_HDR ImageHdr;
4137 	uint32_t NextImage;
4138 	uint32_t i;
4139 	int32_t ChangeParams = FALSE;
4140 	caddr_t Sptr;
4141 	caddr_t Dptr;
4142 
4143 	bzero((caddr_t)AbsWakeUpParms, sizeof (WAKE_UP_PARMS));
4144 
4145 	if ((AifHeader->ImageBase != 0x20000) &&
4146 	    ((AifHeader->RoSize + AifHeader->RwSize) <= 0x20000)) {
4147 		return (FALSE);
4148 	}
4149 
4150 	NextImage = SLI_IMAGE_START - AifHeader->ImageBase;
4151 
4152 	while (BufferSize > NextImage) {
4153 		Sptr = &Buffer[NextImage];
4154 		Dptr = (caddr_t)&ImageHdr;
4155 		for (i = 0; i < sizeof (IMAGE_HDR); i++) {
4156 			Dptr[i] = Sptr[i];
4157 		}
4158 
4159 		if (ImageHdr.BlockSize == 0xffffffff)
4160 			break;
4161 
4162 		switch (ImageHdr.Id.Type) {
4163 		case TEST_PROGRAM:
4164 			break;
4165 		case FUNC_FIRMWARE:
4166 			AbsWakeUpParms->prog_id = ImageHdr.Id;
4167 			ChangeParams = TRUE;
4168 			break;
4169 		case BOOT_BIOS:
4170 			AbsWakeUpParms->u0.boot_bios_id = ImageHdr.Id;
4171 			ChangeParams = TRUE;
4172 			break;
4173 		case SLI1_OVERLAY:
4174 			AbsWakeUpParms->sli1_prog_id = ImageHdr.Id;
4175 			ChangeParams = TRUE;
4176 			break;
4177 		case SLI2_OVERLAY:
4178 			AbsWakeUpParms->sli2_prog_id = ImageHdr.Id;
4179 			ChangeParams = TRUE;
4180 			break;
4181 		case SLI3_OVERLAY:
4182 			AbsWakeUpParms->sli3_prog_id = ImageHdr.Id;
4183 			ChangeParams = TRUE;
4184 			break;
4185 		case SLI4_OVERLAY:
4186 			AbsWakeUpParms->sli4_prog_id = ImageHdr.Id;
4187 			ChangeParams = TRUE;
4188 			break;
4189 		default:
4190 			break;
4191 		}
4192 
4193 		NextImage += ImageHdr.BlockSize;
4194 	}
4195 
4196 	return (ChangeParams);
4197 
4198 } /* emlxs_build_parms() */
4199 
4200 
4201 static uint32_t
emlxs_update_wakeup_parms(emlxs_hba_t * hba,PWAKE_UP_PARMS AbsWakeUpParms,PWAKE_UP_PARMS WakeUpParms)4202 emlxs_update_wakeup_parms(emlxs_hba_t *hba,
4203     PWAKE_UP_PARMS AbsWakeUpParms, PWAKE_UP_PARMS WakeUpParms)
4204 {
4205 	emlxs_port_t *port = &PPORT;
4206 	MAILBOX *mb;
4207 	MAILBOXQ *mbox;
4208 	uint32_t rval = 0;
4209 
4210 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4211 	    KM_NOSLEEP)) == NULL) {
4212 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4213 		    "Unable to allocate mailbox buffer.");
4214 
4215 		return (1);
4216 	}
4217 
4218 	mb = (MAILBOX *)mbox;
4219 
4220 	WakeUpParms->prog_id = AbsWakeUpParms->prog_id;
4221 	WakeUpParms->u0.boot_bios_id = AbsWakeUpParms->u0.boot_bios_id;
4222 	WakeUpParms->sli1_prog_id = AbsWakeUpParms->sli1_prog_id;
4223 	WakeUpParms->sli2_prog_id = AbsWakeUpParms->sli2_prog_id;
4224 	WakeUpParms->sli3_prog_id = AbsWakeUpParms->sli3_prog_id;
4225 	WakeUpParms->sli4_prog_id = AbsWakeUpParms->sli4_prog_id;
4226 
4227 	emlxs_format_update_parms(mbox, WakeUpParms);
4228 
4229 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4230 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4231 		    "Unable to update wakeup parameters: Mailbox cmd=%x "
4232 		    "status=%x", mb->mbxCommand, mb->mbxStatus);
4233 
4234 		rval = 1;
4235 	}
4236 
4237 	if (mbox) {
4238 		kmem_free(mbox, sizeof (MAILBOXQ));
4239 	}
4240 
4241 	return (rval);
4242 
4243 } /* emlxs_update_wakeup_parms() */
4244 
4245 
4246 static uint32_t
emlxs_validate_version(emlxs_hba_t * hba,emlxs_fw_file_t * file,uint32_t id,uint32_t type,char * file_type)4247 emlxs_validate_version(emlxs_hba_t *hba, emlxs_fw_file_t *file, uint32_t id,
4248     uint32_t type, char *file_type)
4249 {
4250 	emlxs_port_t *port = &PPORT;
4251 
4252 	/* Create the version label */
4253 	emlxs_decode_version(file->version, file->label, sizeof (file->label));
4254 
4255 	/* Process the DWC type */
4256 	switch (type) {
4257 	case TEST_PROGRAM:
4258 
4259 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4260 		    "%s: TEST: offset=%08x  version=%08x, %s", file_type,
4261 		    file->offset, file->version, file->label);
4262 
4263 		break;
4264 
4265 	case BOOT_BIOS:
4266 
4267 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4268 		    "%s: BOOT: offset=%08x  version=%08x, %s", file_type,
4269 		    file->offset, file->version, file->label);
4270 
4271 		if (!emlxs_bios_check(hba, id)) {
4272 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4273 			    "BOOT Check: Image not compatible with %s. id=%02x",
4274 			    hba->model_info.model, id);
4275 
4276 			return (EMLXS_IMAGE_INCOMPATIBLE);
4277 		}
4278 
4279 		break;
4280 
4281 	case FUNC_FIRMWARE:	/* Stub */
4282 
4283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4284 		    "%s: STUB: offset=%08x  version=%08x, %s", file_type,
4285 		    file->offset, file->version, file->label);
4286 
4287 		if (!emlxs_stub_check(hba, id)) {
4288 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4289 			    "STUB Check: Image not compatible with %s. id=%02x",
4290 			    hba->model_info.model, id);
4291 
4292 			return (EMLXS_IMAGE_INCOMPATIBLE);
4293 		}
4294 
4295 		break;
4296 
4297 	case SLI1_OVERLAY:
4298 
4299 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4300 		    "%s: SLI1: offset=%08x  version=%08x, %s", file_type,
4301 		    file->offset, file->version, file->label);
4302 
4303 		if (!emlxs_sli1_check(hba, id)) {
4304 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4305 			    "SLI1 Check: Image not compatible with %s. id=%02x",
4306 			    hba->model_info.model, id);
4307 
4308 			return (EMLXS_IMAGE_INCOMPATIBLE);
4309 		}
4310 
4311 		break;
4312 
4313 	case SLI2_OVERLAY:
4314 
4315 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4316 		    "%s: SLI2: offset=%08x  version=%08x, %s", file_type,
4317 		    file->offset, file->version, file->label);
4318 
4319 		if (!emlxs_sli2_check(hba, id)) {
4320 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4321 			    "SLI2 Check: Image not compatible with %s. id=%02x",
4322 			    hba->model_info.model, id);
4323 
4324 			return (EMLXS_IMAGE_INCOMPATIBLE);
4325 		}
4326 
4327 		break;
4328 
4329 	case SLI3_OVERLAY:
4330 
4331 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4332 		    "%s: SLI3: offset=%08x  version=%08x, %s", file_type,
4333 		    file->offset, file->version, file->label);
4334 
4335 		if (!emlxs_sli3_check(hba, id)) {
4336 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4337 			    "SLI3 Check: Image not compatible with %s. id=%02x",
4338 			    hba->model_info.model, id);
4339 
4340 			return (EMLXS_IMAGE_INCOMPATIBLE);
4341 		}
4342 
4343 		break;
4344 
4345 	case SLI4_OVERLAY:
4346 
4347 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4348 		    "%s: SLI4: offset=%08x  version=%08x, %s", file_type,
4349 		    file->offset, file->version, file->label);
4350 
4351 		if (!emlxs_sli4_check(hba, id)) {
4352 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4353 			    "SLI4 Check: Image not compatible with %s. id=%02x",
4354 			    hba->model_info.model, id);
4355 
4356 			return (EMLXS_IMAGE_INCOMPATIBLE);
4357 		}
4358 
4359 		break;
4360 
4361 	case SBUS_FCODE:
4362 
4363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4364 		    "%s: SBUS FCODE: offset=%08x  version=%08x, %s",
4365 		    file_type, file->offset, file->version, file->label);
4366 
4367 		if (!emlxs_sbus_fcode_check(hba, id)) {
4368 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4369 			    "SBUS FCODE Check: Image not compatible with %s. "
4370 			    "id=%02x", hba->model_info.model, id);
4371 
4372 			return (EMLXS_IMAGE_INCOMPATIBLE);
4373 		}
4374 
4375 		break;
4376 
4377 	case KERNEL_CODE:
4378 
4379 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_msg,
4380 		    "%s: KERN: offset=%08x  version=%08x, %s", file_type,
4381 		    file->offset, file->version, file->label);
4382 
4383 		if (!emlxs_kern_check(hba, id)) {
4384 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_incompat_msg,
4385 			    "KERN Check: Image not compatible with %s. id=%02x",
4386 			    hba->model_info.model, id);
4387 
4388 			return (EMLXS_IMAGE_INCOMPATIBLE);
4389 		}
4390 
4391 		break;
4392 
4393 	default:
4394 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4395 		    "%s: Image type not supported. type=%x", file_type, type);
4396 
4397 		return (EMLXS_IMAGE_BAD);
4398 	}
4399 
4400 	return (0);
4401 
4402 } /* emlxs_validate_version() */
4403 
4404 
4405 static void
emlxs_verify_image(emlxs_hba_t * hba,emlxs_fw_image_t * fw_image)4406 emlxs_verify_image(emlxs_hba_t *hba, emlxs_fw_image_t *fw_image)
4407 {
4408 	emlxs_port_t *port = &PPORT;
4409 	emlxs_vpd_t *vpd = &VPD;
4410 	uint32_t i;
4411 	uint32_t count;
4412 
4413 	/* Check for AWC file */
4414 	if (fw_image->awc.version) {
4415 		if (fw_image->awc.version == vpd->postKernRev) {
4416 			fw_image->awc.version = 0;
4417 		}
4418 
4419 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4420 		    "AWC file: KERN: old=%s  new=%s  %s.",
4421 		    vpd->postKernName,
4422 		    fw_image->awc.label,
4423 		    (fw_image->awc.version)? "Update":"Skip");
4424 	}
4425 
4426 	/* Check for BWC file */
4427 	if (fw_image->bwc.version) {
4428 		if (strcmp(vpd->fcode_version, fw_image->bwc.label) == 0) {
4429 			fw_image->bwc.version = 0;
4430 		}
4431 
4432 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4433 		    "BWC file: BOOT: old=%s  new=%s  %s.",
4434 		    vpd->fcode_version,
4435 		    fw_image->bwc.label,
4436 		    (fw_image->bwc.version)? "Update":"Skip");
4437 	}
4438 
4439 	/* Check for DWC file */
4440 	if (fw_image->dwc.version) {
4441 		/* Check for program files */
4442 		count = 0;
4443 		for (i = 0; i < MAX_PROG_TYPES; i++) {
4444 			if (!fw_image->prog[i].version) {
4445 				continue;
4446 			}
4447 
4448 			/* Skip components that don't need updating */
4449 			switch (i) {
4450 			case TEST_PROGRAM:
4451 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4452 				    "DWC file: TEST:             new=%s  "
4453 				    "Update.",
4454 				    fw_image->prog[i].label);
4455 				break;
4456 
4457 			case BOOT_BIOS:
4458 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4459 				    "DWC file: BOOT:             new=%s  "
4460 				    "Update.",
4461 				    fw_image->prog[i].label);
4462 				break;
4463 
4464 			case FUNC_FIRMWARE:
4465 				if (vpd->opFwRev &&
4466 				    (fw_image->prog[i].version ==
4467 				    vpd->opFwRev)) {
4468 					fw_image->prog[i].version = 0;
4469 				}
4470 
4471 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4472 				    "DWC file: STUB: old=%s  new=%s  %s.",
4473 				    vpd->opFwName,
4474 				    fw_image->prog[i].label,
4475 				    (fw_image->prog[i].version)?
4476 				    "Update":"Skip");
4477 				break;
4478 
4479 			case SLI1_OVERLAY:
4480 				if (vpd->sli1FwRev &&
4481 				    (fw_image->prog[i].version ==
4482 				    vpd->sli1FwRev)) {
4483 					fw_image->prog[i].version = 0;
4484 				}
4485 
4486 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4487 				    "DWC file: SLI1: old=%s  new=%s  %s.",
4488 				    vpd->sli1FwName,
4489 				    fw_image->prog[i].label,
4490 				    (fw_image->prog[i].version)?
4491 				    "Update":"Skip");
4492 				break;
4493 
4494 			case SLI2_OVERLAY:
4495 				if (vpd->sli2FwRev &&
4496 				    (fw_image->prog[i].version ==
4497 				    vpd->sli2FwRev)) {
4498 					fw_image->prog[i].version = 0;
4499 				}
4500 
4501 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4502 				    "DWC file: SLI2: old=%s  new=%s  %s.",
4503 				    vpd->sli2FwName,
4504 				    fw_image->prog[i].label,
4505 				    (fw_image->prog[i].version)?
4506 				    "Update":"Skip");
4507 				break;
4508 
4509 			case SLI3_OVERLAY:
4510 				if (vpd->sli3FwRev &&
4511 				    (fw_image->prog[i].version ==
4512 				    vpd->sli3FwRev)) {
4513 					fw_image->prog[i].version = 0;
4514 				}
4515 
4516 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4517 				    "DWC file: SLI3: old=%s  new=%s  %s.",
4518 				    vpd->sli3FwName,
4519 				    fw_image->prog[i].label,
4520 				    (fw_image->prog[i].version)?
4521 				    "Update":"Skip");
4522 				break;
4523 
4524 			case SLI4_OVERLAY:
4525 				if (vpd->sli4FwRev &&
4526 				    (fw_image->prog[i].version ==
4527 				    vpd->sli4FwRev)) {
4528 					fw_image->prog[i].version = 0;
4529 				}
4530 
4531 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4532 				    "DWC file: SLI4: old=%s  new=%s  %s.",
4533 				    vpd->sli4FwRev,
4534 				    fw_image->prog[i].label,
4535 				    (fw_image->prog[i].version)?
4536 				    "Update":"Skip");
4537 				break;
4538 
4539 			default:
4540 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
4541 				    "DWC file: type=%x version=%x label=%s  "
4542 				    "Update.",
4543 				    i,
4544 				    fw_image->prog[i].version,
4545 				    fw_image->prog[i].label);
4546 			}
4547 
4548 			if (fw_image->prog[i].version) {
4549 				count++;
4550 			}
4551 		}
4552 
4553 		if (!count) {
4554 			fw_image->dwc.version = 0;
4555 		}
4556 	}
4557 
4558 	return;
4559 
4560 } /* emlxs_verify_image() */
4561 
4562 
4563 static uint32_t
emlxs_validate_image(emlxs_hba_t * hba,caddr_t Buffer,uint32_t Size,emlxs_fw_image_t * image)4564 emlxs_validate_image(emlxs_hba_t *hba, caddr_t Buffer, uint32_t Size,
4565     emlxs_fw_image_t *image)
4566 {
4567 	emlxs_port_t *port = &PPORT;
4568 	uint32_t ImageType;
4569 	AIF_HDR AifHdr;
4570 	IMAGE_HDR ImageHdr;
4571 	uint32_t NextImage;
4572 	uint32_t count;
4573 	uint32_t FileType;
4574 	uint32_t FileLen = 0;
4575 	uint32_t TotalLen = 0;
4576 	uint32_t *CkSumEnd;
4577 	uint32_t id;
4578 	uint32_t type;
4579 	uint32_t ver;
4580 	uint32_t ImageLength;
4581 	uint32_t BufferSize;
4582 	uint32_t rval = 0;
4583 	caddr_t bptr;
4584 	emlxs_vpd_t *vpd;
4585 
4586 	vpd = &VPD;
4587 
4588 	/* Get image type */
4589 	ImageType = *((uint32_t *)Buffer);
4590 
4591 	/* Pegasus and beyond adapters */
4592 	if ((ImageType == NOP_IMAGE_TYPE) &&
4593 	    !(hba->model_info.chip &
4594 	    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
4595 		bptr = Buffer;
4596 		TotalLen = sizeof (uint32_t);
4597 
4598 		while (TotalLen < Size) {
4599 			if (Size < sizeof (AIF_HDR)) {
4600 				EMLXS_MSGF(EMLXS_CONTEXT,
4601 				    &emlxs_image_bad_msg,
4602 				    "Invalid image header length: 0x%x < 0x%x",
4603 				    Size, sizeof (AIF_HDR));
4604 
4605 				return (EMLXS_IMAGE_BAD);
4606 			}
4607 
4608 			bcopy(bptr, &AifHdr, sizeof (AIF_HDR));
4609 			emlxs_disp_aif_header(hba, &AifHdr);
4610 
4611 			ImageLength = AifHdr.RoSize;
4612 
4613 			/* Validate checksum */
4614 			CkSumEnd =
4615 			    (uint32_t *)(bptr + ImageLength +
4616 			    sizeof (AIF_HDR));
4617 			if (emlxs_valid_cksum((uint32_t *)bptr, CkSumEnd)) {
4618 				EMLXS_MSGF(EMLXS_CONTEXT,
4619 				    &emlxs_image_bad_msg,
4620 				    "Invalid checksum found.");
4621 
4622 				return (EMLXS_IMAGE_BAD);
4623 			}
4624 
4625 			FileType = AifHdr.ZinitBr;
4626 			switch (FileType) {
4627 			case FILE_TYPE_AWC:
4628 				image->awc.offset =
4629 				    (uint32_t)((uintptr_t)bptr -
4630 				    (uintptr_t)Buffer);
4631 				image->awc.version = AifHdr.AVersion;
4632 				image->awc.revcomp = 0;
4633 
4634 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4635 				type = emlxs_type_check(
4636 				    (AifHdr.AVersion & 0xff000000) >> 24);
4637 
4638 				/* Validate the file version */
4639 				if ((rval = emlxs_validate_version(hba,
4640 				    &image->awc, id, type, "AWC file"))) {
4641 					return (rval);
4642 				}
4643 
4644 				break;
4645 
4646 			case FILE_TYPE_BWC:
4647 				image->bwc.offset =
4648 				    (uint32_t)((uintptr_t)bptr -
4649 				    (uintptr_t)Buffer);
4650 				image->bwc.version = AifHdr.AVersion;
4651 				image->bwc.revcomp = 0;
4652 
4653 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4654 				type = emlxs_type_check(
4655 				    (AifHdr.AVersion & 0xff000000) >> 24);
4656 
4657 				/* Validate the file version */
4658 				if ((rval = emlxs_validate_version(hba,
4659 				    &image->bwc, id, type, "BWC file"))) {
4660 					return (rval);
4661 				}
4662 
4663 				break;
4664 
4665 			case FILE_TYPE_DWC:
4666 				image->dwc.offset =
4667 				    (uint32_t)((uintptr_t)bptr -
4668 				    (uintptr_t)Buffer);
4669 				image->dwc.version = AifHdr.AVersion;
4670 				image->dwc.revcomp = 0;
4671 
4672 				id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4673 				type = emlxs_type_check(
4674 				    (AifHdr.AVersion & 0xff000000) >> 24);
4675 
4676 				/* Validate the file version */
4677 				if ((rval = emlxs_validate_version(hba,
4678 				    &image->dwc, id, type, "DWC file"))) {
4679 					return (rval);
4680 				}
4681 
4682 				/* Scan for program types */
4683 				NextImage = sizeof (AIF_HDR) + 4;
4684 				BufferSize = AifHdr.RoSize + AifHdr.RwSize;
4685 
4686 				count = 0;
4687 				while (BufferSize > NextImage) {
4688 					bcopy(&bptr[NextImage], &ImageHdr,
4689 					    sizeof (IMAGE_HDR));
4690 					emlxs_dump_image_header(hba,
4691 					    &ImageHdr);
4692 
4693 					/* Validate block size */
4694 					if (ImageHdr.BlockSize == 0xffffffff) {
4695 						break;
4696 					}
4697 
4698 					type = emlxs_type_check(
4699 					    ImageHdr.Id.Type);
4700 
4701 					/* Calculate the program offset */
4702 					image->prog[type].offset =
4703 					    (uint32_t)((uintptr_t)
4704 					    &bptr[NextImage] -
4705 					    (uintptr_t)Buffer);
4706 
4707 					/* Acquire the versions */
4708 					image->prog[type].version =
4709 					    (ImageHdr.Id.Type << 24) |
4710 					    (ImageHdr.Id.Id << 16) |
4711 					    (ImageHdr.Id.Ver << 8) |
4712 					    ImageHdr.Id.Rev;
4713 
4714 					image->prog[type].revcomp =
4715 					    ImageHdr.Id.un.revcomp;
4716 
4717 					/* Validate the file version */
4718 					if ((rval = emlxs_validate_version(hba,
4719 					    &image->prog[type], ImageHdr.Id.Id,
4720 					    type, "DWC prog"))) {
4721 						return (rval);
4722 					}
4723 
4724 					count++;
4725 					NextImage += ImageHdr.BlockSize;
4726 
4727 				}	/* while () */
4728 
4729 				if (count == 0) {
4730 					EMLXS_MSGF(EMLXS_CONTEXT,
4731 					    &emlxs_image_bad_msg,
4732 					    "DWC file has no PRG images.");
4733 
4734 					return (EMLXS_IMAGE_BAD);
4735 				}
4736 
4737 				break;
4738 			}
4739 
4740 			FileLen =
4741 			    sizeof (AIF_HDR) + ImageLength +
4742 			    sizeof (uint32_t);
4743 			TotalLen += FileLen;
4744 			bptr += FileLen;
4745 		}
4746 	}
4747 
4748 	/* Pre-pegasus adapters */
4749 
4750 	else if (ImageType == NOP_IMAGE_TYPE) {
4751 		if (Size < sizeof (AIF_HDR)) {
4752 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4753 			    "Invalid image header length: 0x%x < 0x%x", Size,
4754 			    sizeof (AIF_HDR));
4755 
4756 			return (EMLXS_IMAGE_BAD);
4757 		}
4758 
4759 		bcopy(Buffer, &AifHdr, sizeof (AIF_HDR));
4760 		emlxs_disp_aif_header(hba, &AifHdr);
4761 
4762 		ImageLength = AifHdr.RoSize + AifHdr.RwSize;
4763 
4764 		if (Size != (sizeof (AIF_HDR) + ImageLength + sizeof (int))) {
4765 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4766 			    "Image length incorrect: 0x%x != 0x%x", Size,
4767 			    sizeof (AIF_HDR) + ImageLength +
4768 			    sizeof (uint32_t));
4769 
4770 			return (EMLXS_IMAGE_BAD);
4771 		}
4772 
4773 		if (AifHdr.ImageBase && AifHdr.ImageBase != 0x20000) {
4774 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4775 			    "Invalid imageBase value %x != 0x20000",
4776 			    AifHdr.ImageBase);
4777 
4778 			return (EMLXS_IMAGE_BAD);
4779 		}
4780 
4781 		CkSumEnd =
4782 		    (uint32_t *)(Buffer + ImageLength + sizeof (AIF_HDR));
4783 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4784 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4785 			    "Invalid checksum found.");
4786 
4787 			return (EMLXS_IMAGE_BAD);
4788 		}
4789 
4790 		image->dwc.offset = 0;
4791 		image->dwc.version = AifHdr.AVersion;
4792 		image->dwc.revcomp = 0;
4793 
4794 		id = (AifHdr.AVersion & 0x00ff0000) >> 16;
4795 		type = emlxs_type_check((AifHdr.AVersion & 0xff000000) >> 24);
4796 
4797 		/* Validate the file version */
4798 		if ((rval = emlxs_validate_version(hba, &image->dwc, id, type,
4799 		    "DWC file"))) {
4800 			return (rval);
4801 		}
4802 
4803 		NextImage = SLI_IMAGE_START - AifHdr.ImageBase;
4804 		while (Size > NextImage) {
4805 			bcopy(&Buffer[NextImage], &ImageHdr,
4806 			    sizeof (IMAGE_HDR));
4807 			emlxs_dump_image_header(hba, &ImageHdr);
4808 
4809 			/* Validate block size */
4810 			if (ImageHdr.BlockSize == 0xffffffff) {
4811 				break;
4812 			}
4813 
4814 			type = emlxs_type_check(ImageHdr.Id.Type);
4815 
4816 			/* Calculate the program offset */
4817 			image->prog[type].offset = NextImage;
4818 
4819 			/* Acquire the versions */
4820 			image->prog[type].version =
4821 			    (ImageHdr.Id.Type << 24) |
4822 			    (ImageHdr.Id.Id << 16) |
4823 			    (ImageHdr.Id.Ver << 8) |
4824 			    ImageHdr.Id.Rev;
4825 
4826 			image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4827 
4828 			/* Validate the file version */
4829 			if ((rval = emlxs_validate_version(hba,
4830 			    &image->prog[type], ImageHdr.Id.Id, type,
4831 			    "DWC prog"))) {
4832 				return (rval);
4833 			}
4834 
4835 			NextImage += ImageHdr.BlockSize;
4836 		}
4837 
4838 	} else { /* PRG File */
4839 
4840 		/* Precheck image size */
4841 		if (Size < sizeof (IMAGE_HDR)) {
4842 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4843 			    "Invalid image header length: 0x%x < 0x%x", Size,
4844 			    sizeof (IMAGE_HDR));
4845 
4846 			return (EMLXS_IMAGE_BAD);
4847 		}
4848 
4849 		bcopy(Buffer, &ImageHdr, sizeof (IMAGE_HDR));
4850 		emlxs_dump_image_header(hba, &ImageHdr);
4851 
4852 		/* Validate block size */
4853 		if (ImageHdr.BlockSize == 0xffffffff) {
4854 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4855 			    "Invalid block size.");
4856 
4857 			return (EMLXS_IMAGE_BAD);
4858 		}
4859 
4860 		ImageLength = ImageHdr.BlockSize;
4861 
4862 		/* Validate image length */
4863 		if (Size != ImageLength) {
4864 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4865 			    "Invalid image length: 0x%x != 0x%x", Size,
4866 			    ImageLength);
4867 
4868 			return (EMLXS_IMAGE_BAD);
4869 		}
4870 
4871 		/* Validate Checksum */
4872 		CkSumEnd =
4873 		    (uint32_t *)Buffer + (ImageLength / sizeof (uint32_t)) -
4874 		    1;
4875 		if (emlxs_valid_cksum((uint32_t *)Buffer, CkSumEnd)) {
4876 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
4877 			    "Invalid checksum found.");
4878 
4879 			return (EMLXS_IMAGE_BAD);
4880 		}
4881 
4882 		type = emlxs_type_check(ImageHdr.Id.Type);
4883 
4884 		/* Calculate the program offset */
4885 		image->prog[type].offset = 0;
4886 
4887 		/* Acquire the versions */
4888 		image->prog[type].version =
4889 		    (ImageHdr.Id.Type << 24) |
4890 		    (ImageHdr.Id.Id << 16) |
4891 		    (ImageHdr.Id.Ver << 8) |
4892 		    ImageHdr.Id.Rev;
4893 
4894 		image->prog[type].revcomp = ImageHdr.Id.un.revcomp;
4895 
4896 		/* Validate the file version */
4897 		if ((rval = emlxs_validate_version(hba, &image->prog[type],
4898 		    ImageHdr.Id.Id, type, "DWC file"))) {
4899 			return (rval);
4900 		}
4901 	}
4902 
4903 	/*
4904 	 * This checks if a DragonFly (pre-V2 ASIC) SLI2
4905 	 * image file is < version 3.8
4906 	 */
4907 	if (FC_JEDEC_ID(vpd->biuRev) == DRAGONFLY_JEDEC_ID) {
4908 		ver = (image->prog[SLI2_OVERLAY].version &
4909 		    0x0000ff00) >> 8;
4910 
4911 		if (ver >= 0x38) {
4912 			EMLXS_MSGF(EMLXS_CONTEXT,
4913 			    &emlxs_image_incompat_msg,
4914 			    "ASIC Check: Image requires DragonFly "
4915 			    "V2 ASIC");
4916 
4917 			return (EMLXS_IMAGE_INCOMPATIBLE);
4918 		}
4919 	}
4920 
4921 	return (0);
4922 
4923 } /* emlxs_validate_image() */
4924 
4925 
4926 static uint32_t
emlxs_update_exp_rom(emlxs_hba_t * hba,PWAKE_UP_PARMS WakeUpParms)4927 emlxs_update_exp_rom(emlxs_hba_t *hba, PWAKE_UP_PARMS WakeUpParms)
4928 {
4929 	emlxs_port_t *port = &PPORT;
4930 	MAILBOXQ *mbox;
4931 	MAILBOX *mb;
4932 	uint32_t next_address;
4933 	uint32_t rval = 0;
4934 
4935 	if (WakeUpParms->u1.EROM_prog_wd[0] == 0) {
4936 		return (1);
4937 	}
4938 
4939 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
4940 	    KM_NOSLEEP)) == NULL) {
4941 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4942 		    "Unable to allocate mailbox buffer.");
4943 
4944 		return (1);
4945 	}
4946 
4947 	bzero(mbox, sizeof (MAILBOXQ));
4948 
4949 	mb = (MAILBOX *)mbox;
4950 	mb->mbxCommand = MBX_LOAD_EXP_ROM;
4951 	mb->un.varLdExpRom.step = EROM_CMD_FIND_IMAGE;
4952 	mb->un.varLdExpRom.progress = 0;
4953 	mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4954 	mbox->mbox_cmpl = NULL;
4955 
4956 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
4957 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4958 		    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
4959 		    mb->mbxCommand, mb->mbxStatus);
4960 
4961 		rval = 1;
4962 
4963 		goto SLI_DOWNLOAD_EXIT;
4964 	}
4965 
4966 	if (mb->un.varLdExpRom.progress == EROM_RSP_COPY_DONE) {
4967 		(void) emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
4968 
4969 		rval = 1;
4970 		goto SLI_DOWNLOAD_EXIT;
4971 	}
4972 
4973 	if (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_STARTED) {
4974 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
4975 		    "Invalid exp ROM progress. progress=%x",
4976 		    mb->un.varLdExpRom.progress);
4977 
4978 		rval = 1;
4979 
4980 		goto SLI_DOWNLOAD_EXIT;
4981 	}
4982 
4983 	/*
4984 	 * continue Erase
4985 	 */
4986 	while (mb->un.varLdExpRom.progress != EROM_RSP_ERASE_COMPLETE) {
4987 
4988 		next_address = mb->un.varLdExpRom.dl_to_adr;
4989 
4990 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
4991 
4992 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
4993 		mb->un.varLdExpRom.step = EROM_CMD_CONTINUE_ERASE;
4994 		mb->un.varLdExpRom.dl_to_adr = next_address;
4995 		mb->un.varLdExpRom.progress = 0;
4996 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
4997 		mbox->mbox_cmpl = NULL;
4998 
4999 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5000 		    MBX_SUCCESS) {
5001 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5002 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
5003 			    mb->mbxCommand, mb->mbxStatus);
5004 
5005 			rval = 1;
5006 			goto SLI_DOWNLOAD_EXIT;
5007 		}
5008 
5009 	}
5010 
5011 	while (mb->un.varLdExpRom.progress != EROM_RSP_COPY_DONE) {
5012 		next_address = mb->un.varLdExpRom.dl_to_adr;
5013 
5014 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
5015 
5016 		mb->mbxCommand = MBX_LOAD_EXP_ROM;
5017 		mb->un.varLdExpRom.step = EROM_CMD_COPY;
5018 		mb->un.varLdExpRom.dl_to_adr = next_address;
5019 		mb->un.varLdExpRom.progress = 0;
5020 		mb->un.varLdExpRom.un.prog_id = WakeUpParms->u1.EROM_prog_id;
5021 		mbox->mbox_cmpl = NULL;
5022 
5023 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5024 		    MBX_SUCCESS) {
5025 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5026 			    "Unable to load exp ROM. Mailbox cmd=%x status=%x",
5027 			    mb->mbxCommand, mb->mbxStatus);
5028 
5029 			rval = 1;
5030 
5031 			goto SLI_DOWNLOAD_EXIT;
5032 		}
5033 	}
5034 
5035 	rval = emlxs_update_wakeup_parms(hba, WakeUpParms, WakeUpParms);
5036 
5037 SLI_DOWNLOAD_EXIT:
5038 
5039 	if (mbox) {
5040 		kmem_free(mbox, sizeof (MAILBOXQ));
5041 	}
5042 
5043 	return (rval);
5044 
5045 } /* emlxs_update_exp_rom() */
5046 
5047 
5048 /*
5049  *
5050  * FUNCTION NAME: emlxs_start_abs_download_2mb
5051  *
5052  * DESCRIPTION: Perform absolute download for 2 MB flash.  A incoming
5053  *              buffer may consist of more than 1 file.  This function
5054  *              will parse the buffer to find all the files.
5055  *
5056  *
5057  * PARAMETERS:
5058  *
5059  *
5060  * RETURNS:
5061  *
5062  */
5063 /* ARGSUSED */
5064 static uint32_t
emlxs_start_abs_download_2mb(emlxs_hba_t * hba,caddr_t buffer,uint32_t len,uint32_t offline,emlxs_fw_image_t * fw_image)5065 emlxs_start_abs_download_2mb(emlxs_hba_t *hba, caddr_t buffer, uint32_t len,
5066     uint32_t offline, emlxs_fw_image_t *fw_image)
5067 {
5068 	emlxs_port_t *port = &PPORT;
5069 	uint32_t rval = 0;
5070 
5071 	/* If nothing to download then quit now */
5072 	if (!fw_image->awc.version &&
5073 	    !fw_image->dwc.version &&
5074 	    !fw_image->bwc.version) {
5075 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_msg,
5076 		    "Nothing new to update.  Exiting.");
5077 		return (0);
5078 	}
5079 
5080 	/*
5081 	 * Everything checks out, now to just do it
5082 	 */
5083 	if (offline) {
5084 		if (emlxs_offline(hba, 0) != FC_SUCCESS) {
5085 			return (EMLXS_OFFLINE_FAILED);
5086 		}
5087 
5088 		if (EMLXS_SLI_HBA_RESET(hba, 1, 1, 0) != FC_SUCCESS) {
5089 			return (EMLXS_OFFLINE_FAILED);
5090 		}
5091 	}
5092 
5093 	if (fw_image->awc.version) {
5094 		rval = emlxs_proc_abs_2mb(hba,
5095 		    (buffer + fw_image->awc.offset),
5096 		    FILE_TYPE_AWC, 0);
5097 
5098 		if (rval) {
5099 			goto SLI_DOWNLOAD_2MB_EXIT;
5100 		}
5101 	}
5102 
5103 	if (fw_image->bwc.version) {
5104 		rval = emlxs_proc_abs_2mb(hba,
5105 		    (buffer + fw_image->bwc.offset),
5106 		    FILE_TYPE_BWC,
5107 		    (fw_image->dwc.version)? ALLext:BWCext);
5108 
5109 		if (rval) {
5110 			goto SLI_DOWNLOAD_2MB_EXIT;
5111 		}
5112 	}
5113 
5114 	if (fw_image->dwc.version) {
5115 		rval = emlxs_proc_rel_2mb(hba, buffer, fw_image);
5116 
5117 		if (rval) {
5118 			goto SLI_DOWNLOAD_2MB_EXIT;
5119 		}
5120 	}
5121 
5122 SLI_DOWNLOAD_2MB_EXIT:
5123 
5124 	if (offline) {
5125 		(void) emlxs_online(hba);
5126 	}
5127 
5128 	return (rval);
5129 
5130 } /* emlxs_start_abs_download_2mb() */
5131 
5132 
5133 /*
5134  *
5135  * FUNCTION NAME: emlxs_proc_abs_2mb
5136  *
5137  * DESCRIPTION: Given one of the 3 file types(awc/bwc/dwc), it will reset
5138  *              the port and download the file with sliIssueMbCommand()
5139  *
5140  *
5141  * PARAMETERS:
5142  *
5143  *
5144  * RETURNS:
5145  *
5146  */
5147 static uint32_t
emlxs_proc_abs_2mb(emlxs_hba_t * hba,caddr_t EntireBuffer,uint32_t FileType,uint32_t extType)5148 emlxs_proc_abs_2mb(emlxs_hba_t *hba, caddr_t EntireBuffer,
5149     uint32_t FileType, uint32_t extType)
5150 {
5151 	emlxs_port_t *port = &PPORT;
5152 	PAIF_HDR AifHdr;
5153 	caddr_t Buffer = NULL;
5154 	caddr_t DataBuffer = NULL;
5155 	uint32_t *Src;
5156 	uint32_t *Dst;
5157 	MAILBOXQ *mbox;
5158 	MAILBOX *mb;
5159 	uint32_t DlByteCount;
5160 	uint32_t rval = 0;
5161 	uint32_t SegSize = DL_SLIM_SEG_BYTE_COUNT;
5162 	uint32_t DlToAddr;
5163 	uint32_t DlCount;
5164 	WAKE_UP_PARMS AbsWakeUpParms;
5165 	uint32_t i;
5166 	uint32_t NextAddr;
5167 	uint32_t EraseByteCount;
5168 	uint32_t AreaId;
5169 	uint32_t RspProgress = 0;
5170 	uint32_t ParamsChg;
5171 
5172 	AifHdr = (PAIF_HDR)EntireBuffer;
5173 	DlByteCount = AifHdr->RoSize + AifHdr->RwSize;
5174 	DlToAddr = AifHdr->ImageBase;
5175 
5176 	if ((DataBuffer = (caddr_t)kmem_zalloc(DL_SLIM_SEG_BYTE_COUNT,
5177 	    KM_NOSLEEP)) == NULL) {
5178 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5179 		    "%x: Unable to allocate data buffer.", FileType);
5180 
5181 		return (EMLXS_IMAGE_FAILED);
5182 	}
5183 
5184 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
5185 	    KM_NOSLEEP)) == NULL) {
5186 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5187 		    "%x: Unable to allocate mailbox buffer.", FileType);
5188 
5189 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
5190 
5191 		return (EMLXS_IMAGE_FAILED);
5192 	}
5193 
5194 	mb = (MAILBOX *)mbox;
5195 
5196 	Buffer = EntireBuffer + sizeof (AIF_HDR);
5197 
5198 	switch (FileType) {
5199 	case FILE_TYPE_AWC:
5200 		ParamsChg = 0;
5201 		break;
5202 
5203 	case FILE_TYPE_BWC:
5204 		rval = emlxs_build_parms_2mb_bwc(hba,
5205 		    AifHdr, extType, &AbsWakeUpParms);
5206 
5207 		if (rval == FALSE) {
5208 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5209 			    "BWC build parms failed.");
5210 
5211 			rval = EMLXS_IMAGE_FAILED;
5212 
5213 			goto EXIT_ABS_DOWNLOAD;
5214 		}
5215 		ParamsChg = 1;
5216 		break;
5217 
5218 	default:
5219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_image_bad_msg,
5220 		    "Invalid file type: %x", FileType);
5221 
5222 		rval = EMLXS_IMAGE_BAD;
5223 
5224 		goto EXIT_ABS_DOWNLOAD;
5225 	}
5226 
5227 	EraseByteCount = AifHdr->Area_Size;
5228 	AreaId = AifHdr->Area_ID;
5229 
5230 	emlxs_format_load_area_cmd(mbox,
5231 	    DlToAddr,
5232 	    EraseByteCount,
5233 	    ERASE_FLASH,
5234 	    0, DL_FROM_SLIM_OFFSET, AreaId, MBX_LOAD_AREA, CMD_START_ERASE);
5235 
5236 	if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) != MBX_SUCCESS) {
5237 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5238 		    "%x: Could not erase 2MB Flash: Mailbox cmd=%x status=%x",
5239 		    FileType, mb->mbxCommand, mb->mbxStatus);
5240 
5241 		rval = EMLXS_IMAGE_FAILED;
5242 
5243 		goto EXIT_ABS_DOWNLOAD;
5244 	}
5245 
5246 	while (mb->un.varLdArea.progress != RSP_ERASE_COMPLETE) {
5247 		NextAddr = mb->un.varLdArea.dl_to_adr;
5248 
5249 		emlxs_format_load_area_cmd(mbox,
5250 		    NextAddr,
5251 		    EraseByteCount,
5252 		    ERASE_FLASH,
5253 		    0,
5254 		    DL_FROM_SLIM_OFFSET,
5255 		    AreaId, MBX_LOAD_AREA, CMD_CONTINUE_ERASE);
5256 
5257 		if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5258 		    MBX_SUCCESS) {
5259 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5260 			    "%x: Could not erase 2MB Flash2: Mailbox cmd=%x "
5261 			    "status=%x", FileType, mb->mbxCommand,
5262 			    mb->mbxStatus);
5263 
5264 			rval = EMLXS_IMAGE_FAILED;
5265 
5266 			goto EXIT_ABS_DOWNLOAD;
5267 		}
5268 	}
5269 
5270 	while (DlByteCount) {
5271 		if (DlByteCount >= SegSize)
5272 			DlCount = SegSize;
5273 		else
5274 			DlCount = DlByteCount;
5275 
5276 		DlByteCount -= DlCount;
5277 
5278 		Dst = (uint32_t *)DataBuffer;
5279 		Src = (uint32_t *)Buffer;
5280 
5281 		for (i = 0; i < (DlCount / 4); i++) {
5282 			*Dst = *Src;
5283 			Dst++;
5284 			Src++;
5285 		}
5286 
5287 		WRITE_SLIM_COPY(hba, (uint32_t *)DataBuffer,
5288 		    (volatile uint32_t *)((volatile char *)
5289 		    hba->sli.sli3.slim_addr + sizeof (MAILBOX)),
5290 		    (DlCount / sizeof (uint32_t)));
5291 
5292 		if ((RspProgress == RSP_DOWNLOAD_MORE) || (RspProgress == 0)) {
5293 			emlxs_format_load_area_cmd(mbox,
5294 			    DlToAddr,
5295 			    DlCount,
5296 			    PROGRAM_FLASH,
5297 			    (DlByteCount) ? 0 : 1,
5298 			    DL_FROM_SLIM_OFFSET,
5299 			    AreaId,
5300 			    MBX_LOAD_AREA,
5301 			    (DlByteCount) ? CMD_DOWNLOAD : CMD_END_DOWNLOAD);
5302 
5303 			if (EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0) !=
5304 			    MBX_SUCCESS) {
5305 				EMLXS_MSGF(EMLXS_CONTEXT,
5306 				    &emlxs_download_failed_msg,
5307 				    "%x: Could not program 2MB Flash: Mailbox "
5308 				    "cmd=%x status=%x", FileType,
5309 				    mb->mbxCommand, mb->mbxStatus);
5310 
5311 				rval = EMLXS_IMAGE_FAILED;
5312 
5313 				goto EXIT_ABS_DOWNLOAD;
5314 			}
5315 		}
5316 
5317 		RspProgress = mb->un.varLdArea.progress;
5318 
5319 		Buffer += DlCount;
5320 		DlToAddr += DlCount;
5321 	}
5322 
5323 #ifdef FMA_SUPPORT
5324 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
5325 	    != DDI_FM_OK) {
5326 		EMLXS_MSGF(EMLXS_CONTEXT,
5327 		    &emlxs_invalid_access_handle_msg, NULL);
5328 
5329 		rval = EMLXS_IMAGE_FAILED;
5330 
5331 		goto EXIT_ABS_DOWNLOAD;
5332 	}
5333 #endif  /* FMA_SUPPORT */
5334 
5335 	if (RspProgress != RSP_DOWNLOAD_DONE) {
5336 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5337 		    "%x: Failed download response received. %x", FileType,
5338 		    RspProgress);
5339 
5340 		rval = EMLXS_IMAGE_FAILED;
5341 
5342 		goto EXIT_ABS_DOWNLOAD;
5343 	}
5344 
5345 	if (ParamsChg) {
5346 		if (emlxs_update_wakeup_parms(hba, &AbsWakeUpParms,
5347 		    &AbsWakeUpParms)) {
5348 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5349 			    "%x: Unable to update parms.", FileType);
5350 
5351 			rval = EMLXS_IMAGE_FAILED;
5352 		}
5353 	}
5354 
5355 EXIT_ABS_DOWNLOAD:
5356 
5357 	if (DataBuffer) {
5358 		kmem_free(DataBuffer, DL_SLIM_SEG_BYTE_COUNT);
5359 	}
5360 
5361 	if (mbox) {
5362 		kmem_free(mbox, sizeof (MAILBOXQ));
5363 	}
5364 
5365 	return (rval);
5366 
5367 } /* emlxs_proc_abs_2mb() */
5368 
5369 
5370 static void
emlxs_format_load_area_cmd(MAILBOXQ * mbq,uint32_t Base,uint32_t DlByteCount,uint32_t Function,uint32_t Complete,uint32_t DataOffset,uint32_t AreaId,uint8_t MbxCmd,uint32_t StepCmd)5371 emlxs_format_load_area_cmd(MAILBOXQ * mbq,
5372     uint32_t Base,
5373     uint32_t DlByteCount,
5374     uint32_t Function,
5375     uint32_t Complete,
5376     uint32_t DataOffset, uint32_t AreaId, uint8_t MbxCmd, uint32_t StepCmd)
5377 {
5378 	MAILBOX *mb = (MAILBOX *)mbq;
5379 
5380 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
5381 
5382 	mb->mbxCommand = MbxCmd;
5383 	mb->mbxOwner = OWN_HOST;
5384 	mb->un.varLdArea.update_flash = 1;
5385 	mb->un.varLdArea.erase_or_prog = Function;
5386 	mb->un.varLdArea.dl_to_adr = Base;
5387 	mb->un.varLdArea.dl_len = DlByteCount;
5388 	mb->un.varLdArea.load_cmplt = Complete;
5389 	mb->un.varLdArea.method = DL_FROM_SLIM;
5390 	mb->un.varLdArea.area_id = AreaId;
5391 	mb->un.varLdArea.step = StepCmd;
5392 	mb->un.varLdArea.un.dl_from_slim_offset = DataOffset;
5393 	mbq->mbox_cmpl = NULL;
5394 
5395 } /* emlxs_format_load_area_cmd() */
5396 
5397 
5398 /* ARGSUSED */
5399 static uint32_t
emlxs_build_parms_2mb_bwc(emlxs_hba_t * hba,PAIF_HDR AifHdr,uint32_t extType,PWAKE_UP_PARMS AbsWakeUpParms)5400 emlxs_build_parms_2mb_bwc(emlxs_hba_t *hba,
5401     PAIF_HDR AifHdr, uint32_t extType, PWAKE_UP_PARMS AbsWakeUpParms)
5402 {
5403 	emlxs_port_t *port = &PPORT;
5404 	uint32_t pId[2];
5405 	uint32_t returnStat;
5406 
5407 	/* Read wakeup paramters */
5408 	if (emlxs_read_wakeup_parms(hba, AbsWakeUpParms, 0) ==
5409 	    (uint32_t)CFG_DATA_NO_REGION) {
5410 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5411 		    "Unable to get BWC parameters.");
5412 		return (FALSE);
5413 	}
5414 
5415 	pId[0] = AifHdr->AVersion;
5416 	pId[1] = 0;
5417 
5418 	if (extType == BWCext) {
5419 		AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
5420 		AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
5421 		AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5422 		AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5423 	}
5424 
5425 	else if (extType == ALLext) {
5426 		if (!AbsWakeUpParms->u0.boot_bios_wd[0]) {
5427 			/* case of EROM inactive */
5428 			AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5429 			AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5430 		} else {
5431 			/* case of EROM active */
5432 			if (AbsWakeUpParms->u0.boot_bios_wd[0] == pId[0]) {
5433 				/* same ID */
5434 				AbsWakeUpParms->u0.boot_bios_wd[0] = pId[0];
5435 				AbsWakeUpParms->u0.boot_bios_wd[1] = pId[1];
5436 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5437 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5438 			} else {
5439 				/* different ID */
5440 				AbsWakeUpParms->u1.EROM_prog_wd[0] = pId[0];
5441 				AbsWakeUpParms->u1.EROM_prog_wd[1] = pId[1];
5442 
5443 				returnStat =
5444 				    emlxs_update_exp_rom(hba, AbsWakeUpParms);
5445 
5446 				if (returnStat) {
5447 					AbsWakeUpParms->u0.boot_bios_wd[0] =
5448 					    pId[0];
5449 					AbsWakeUpParms->u0.boot_bios_wd[1] =
5450 					    pId[1];
5451 				}
5452 			}
5453 		}
5454 	}
5455 
5456 	return (TRUE);
5457 
5458 } /* emlxs_build_parms_2mb_bwc() */
5459 
5460 
5461 extern uint32_t
emlxs_get_max_sram(emlxs_hba_t * hba,uint32_t * MaxRbusSize,uint32_t * MaxIbusSize)5462 emlxs_get_max_sram(emlxs_hba_t *hba, uint32_t *MaxRbusSize,
5463     uint32_t *MaxIbusSize)
5464 {
5465 	emlxs_port_t *port = &PPORT;
5466 	MAILBOXQ *mbox;
5467 	MAILBOX *mb;
5468 	uint32_t *Uptr;
5469 	uint32_t rval = 0;
5470 
5471 	if (MaxRbusSize) {
5472 		*MaxRbusSize = 0;
5473 	}
5474 
5475 	if (MaxIbusSize) {
5476 		*MaxIbusSize = 0;
5477 	}
5478 
5479 	if ((mbox = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
5480 	    KM_NOSLEEP)) == NULL) {
5481 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5482 		    "Unable to allocate mailbox buffer.");
5483 
5484 		return (1);
5485 	}
5486 
5487 	mb = (MAILBOX *)mbox;
5488 
5489 	emlxs_format_dump(hba, mbox, DMP_MEM_REG, 0, 2, MAX_RBUS_SRAM_SIZE_ADR);
5490 
5491 	if ((rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_WAIT, 0)) !=
5492 	    MBX_SUCCESS) {
5493 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_download_failed_msg,
5494 		    "Unable to get SRAM size: Mailbox cmd=%x status=%x",
5495 		    mb->mbxCommand, mb->mbxStatus);
5496 
5497 		rval = 1;
5498 
5499 		goto Exit_Function;
5500 	}
5501 
5502 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5503 		EMLXS_MPDATA_SYNC(hba->sli.sli4.dump_region.dma_handle, 0,
5504 		    hba->sli.sli4.dump_region.size, DDI_DMA_SYNC_FORKERNEL);
5505 		Uptr = (uint32_t *)hba->sli.sli4.dump_region.virt;
5506 	} else {
5507 		Uptr = (uint32_t *)&mb->un.varDmp.resp_offset;
5508 	}
5509 
5510 	if (MaxRbusSize) {
5511 		*MaxRbusSize = Uptr[0];
5512 	}
5513 
5514 	if (MaxIbusSize) {
5515 		*MaxIbusSize = Uptr[1];
5516 	}
5517 
5518 Exit_Function:
5519 
5520 	if (mbox) {
5521 		kmem_free(mbox, sizeof (MAILBOXQ));
5522 	}
5523 
5524 #ifdef FMA_SUPPORT
5525 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5526 		if (emlxs_fm_check_dma_handle(hba,
5527 		    hba->sli.sli4.dump_region.dma_handle) != DDI_FM_OK) {
5528 			EMLXS_MSGF(EMLXS_CONTEXT,
5529 			    &emlxs_invalid_dma_handle_msg,
5530 			    "get_max_sram: hdl=%p",
5531 			    hba->sli.sli4.dump_region.dma_handle);
5532 			rval = 1;
5533 		}
5534 	}
5535 #endif  /* FMA_SUPPORT */
5536 
5537 	return (rval);
5538 
5539 } /* emlxs_get_max_sram() */
5540 
5541 
5542 static uint32_t
emlxs_kern_check(emlxs_hba_t * hba,uint32_t version)5543 emlxs_kern_check(emlxs_hba_t *hba, uint32_t version)
5544 {
5545 	uint8_t *ptr;
5546 	uint8_t ver;
5547 
5548 	ver = version & 0xff;
5549 	ptr = hba->model_info.pt_FF;
5550 
5551 	while (*ptr) {
5552 		if (*ptr++ == ver) {
5553 			return (1);
5554 		}
5555 	}
5556 
5557 	return (0);
5558 
5559 } /* emlxs_kern_check() */
5560 
5561 static uint32_t
emlxs_stub_check(emlxs_hba_t * hba,uint32_t version)5562 emlxs_stub_check(emlxs_hba_t *hba, uint32_t version)
5563 {
5564 	uint8_t *ptr;
5565 	uint8_t ver;
5566 
5567 	ver = version & 0xff;
5568 	ptr = hba->model_info.pt_2;
5569 
5570 	while (*ptr) {
5571 		if (*ptr++ == ver) {
5572 			return (1);
5573 		}
5574 	}
5575 
5576 	return (0);
5577 
5578 } /* emlxs_stub_check() */
5579 
5580 static uint32_t
emlxs_bios_check(emlxs_hba_t * hba,uint32_t version)5581 emlxs_bios_check(emlxs_hba_t *hba, uint32_t version)
5582 {
5583 	uint8_t *ptr;
5584 	uint8_t ver;
5585 
5586 	ver = version & 0xff;
5587 	ptr = hba->model_info.pt_3;
5588 
5589 	while (*ptr) {
5590 		if (*ptr++ == ver) {
5591 			return (1);
5592 		}
5593 	}
5594 
5595 	return (0);
5596 
5597 } /* emlxs_bios_check() */
5598 
5599 static uint32_t
emlxs_sli1_check(emlxs_hba_t * hba,uint32_t version)5600 emlxs_sli1_check(emlxs_hba_t *hba, uint32_t version)
5601 {
5602 	uint8_t *ptr;
5603 	uint8_t ver;
5604 
5605 	ver = version & 0xff;
5606 	ptr = hba->model_info.pt_6;
5607 
5608 	while (*ptr) {
5609 		if (*ptr++ == ver) {
5610 			return (1);
5611 		}
5612 	}
5613 
5614 	return (0);
5615 
5616 } /* emlxs_sli1_check() */
5617 
5618 static uint32_t
emlxs_sli2_check(emlxs_hba_t * hba,uint32_t version)5619 emlxs_sli2_check(emlxs_hba_t *hba, uint32_t version)
5620 {
5621 	uint8_t *ptr;
5622 	uint8_t ver;
5623 
5624 	ver = version & 0xff;
5625 	ptr = hba->model_info.pt_7;
5626 
5627 	while (*ptr) {
5628 		if (*ptr++ == ver) {
5629 			return (1);
5630 		}
5631 	}
5632 
5633 	return (0);
5634 
5635 } /* emlxs_sli2_check() */
5636 
5637 static uint32_t
emlxs_sli3_check(emlxs_hba_t * hba,uint32_t version)5638 emlxs_sli3_check(emlxs_hba_t *hba, uint32_t version)
5639 {
5640 	uint8_t *ptr;
5641 	uint8_t ver;
5642 
5643 	ver = version & 0xff;
5644 	ptr = hba->model_info.pt_B;
5645 
5646 	while (*ptr) {
5647 		if (*ptr++ == ver) {
5648 			return (1);
5649 		}
5650 	}
5651 
5652 	return (0);
5653 
5654 } /* emlxs_sli3_check() */
5655 
5656 
5657 static uint32_t
emlxs_sli4_check(emlxs_hba_t * hba,uint32_t version)5658 emlxs_sli4_check(emlxs_hba_t *hba, uint32_t version)
5659 {
5660 	uint8_t *ptr;
5661 	uint8_t ver;
5662 
5663 	ver = version & 0xff;
5664 	ptr = hba->model_info.pt_E;
5665 
5666 	while (*ptr) {
5667 		if (*ptr++ == ver) {
5668 			return (1);
5669 		}
5670 	}
5671 
5672 	return (0);
5673 
5674 } /* emlxs_sli4_check() */
5675 
5676 
5677 static uint32_t
emlxs_sbus_fcode_check(emlxs_hba_t * hba,uint32_t version)5678 emlxs_sbus_fcode_check(emlxs_hba_t *hba, uint32_t version)
5679 {
5680 	uint8_t *ptr;
5681 	uint8_t ver;
5682 
5683 	ver = version & 0xff;
5684 	ptr = hba->model_info.pt_A;
5685 
5686 	while (*ptr) {
5687 		if (*ptr++ == ver) {
5688 			return (1);
5689 		}
5690 	}
5691 
5692 	return (0);
5693 
5694 } /* emlxs_sbus_fcode_check() */
5695 
5696 
5697 static uint32_t
emlxs_type_check(uint32_t type)5698 emlxs_type_check(uint32_t type)
5699 {
5700 	if (type == 0xff) {
5701 		return (KERNEL_CODE);
5702 	}
5703 
5704 	if (type >= MAX_PROG_TYPES) {
5705 		return (RESERVED_D);
5706 	}
5707 
5708 	return (type);
5709 
5710 } /* emlxs_type_check() */
5711 
5712 
5713 extern int32_t
emlxs_boot_code_disable(emlxs_hba_t * hba)5714 emlxs_boot_code_disable(emlxs_hba_t *hba)
5715 {
5716 	emlxs_port_t *port = &PPORT;
5717 	PROG_ID Id;
5718 	emlxs_vpd_t *vpd;
5719 	uint8_t boot_state = 0;
5720 
5721 	vpd = &VPD;
5722 
5723 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5724 		return (EMLXS_OP_NOT_SUP);
5725 	}
5726 
5727 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5728 		/* Read Boot Config */
5729 		if (emlxs_get_boot_config(hba, &boot_state)) {
5730 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5731 			    "boot_code_enable: Unable to get boot config.");
5732 
5733 			return (FC_FAILURE);
5734 		}
5735 
5736 		/* Check if boot code is already disabled */
5737 		if (! boot_state) {
5738 			return (FC_SUCCESS);
5739 		}
5740 
5741 		/* Disable boot code */
5742 		boot_state = 0;
5743 		if (emlxs_set_boot_config(hba, boot_state)) {
5744 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5745 			    "boot_code_enable: Unable to set boot config.");
5746 
5747 			return (FC_FAILURE);
5748 		}
5749 
5750 		/* Now read the boot config again to verify */
5751 		if (emlxs_get_boot_config(hba, &boot_state)) {
5752 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5753 			    "boot_code_enable: Unable to get boot config.");
5754 
5755 			return (FC_FAILURE);
5756 		}
5757 
5758 		/* return the result */
5759 		return ((boot_state == 0) ? FC_SUCCESS : FC_FAILURE);
5760 	} else {
5761 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5762 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5763 			    "boot_code_disable: Unable to read wake up parms.");
5764 
5765 			return (FC_FAILURE);
5766 		}
5767 
5768 		/* Check if boot code is already disabled */
5769 		if (hba->wakeup_parms.u0.boot_bios_wd[0] == 0) {
5770 			return (FC_SUCCESS);
5771 		}
5772 
5773 		/* Make sure EROM entry has copy of boot bios entry */
5774 		if (!(hba->model_info.chip &
5775 		    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP)) &&
5776 		    (hba->wakeup_parms.u0.boot_bios_wd[0] !=
5777 		    hba->wakeup_parms.u1.EROM_prog_wd[0]) &&
5778 		    (hba->wakeup_parms.u0.boot_bios_wd[1] !=
5779 		    hba->wakeup_parms.u1.EROM_prog_wd[1])) {
5780 			(void) emlxs_update_boot_wakeup_parms(hba,
5781 			    &hba->wakeup_parms,
5782 			    &hba->wakeup_parms.u0.boot_bios_id, 1);
5783 		}
5784 
5785 		/* Update the bios id with a zero id */
5786 		/* Don't load the EROM this time */
5787 		bzero(&Id, sizeof (PROG_ID));
5788 		(void) emlxs_update_boot_wakeup_parms(hba,
5789 		    &hba->wakeup_parms, &Id, 0);
5790 
5791 		/* Now read the parms again to verify */
5792 		(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5793 		emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5794 		    vpd->boot_version, sizeof (vpd->boot_version));
5795 		/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5796 
5797 		/* Return the result */
5798 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] == 0) ?
5799 		    FC_SUCCESS : FC_FAILURE);
5800 	}
5801 
5802 } /* emlxs_boot_code_disable() */
5803 
5804 
5805 extern int32_t
emlxs_boot_code_enable(emlxs_hba_t * hba)5806 emlxs_boot_code_enable(emlxs_hba_t *hba)
5807 {
5808 	emlxs_port_t *port = &PPORT;
5809 	emlxs_vpd_t *vpd;
5810 	PROG_ID load_list[MAX_LOAD_ENTRY];
5811 	uint32_t i;
5812 	uint32_t count;
5813 	uint8_t boot_state = 0;
5814 
5815 	vpd = &VPD;
5816 
5817 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5818 		return (FC_SUCCESS);
5819 	}
5820 
5821 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5822 		/* Read Boot Config */
5823 		if (emlxs_get_boot_config(hba, &boot_state)) {
5824 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5825 			    "boot_code_enable: Unable to get boot config.");
5826 
5827 			return (FC_FAILURE);
5828 		}
5829 
5830 		/* Check if boot code is already enabled */
5831 		if (boot_state) {
5832 			return (FC_SUCCESS);
5833 		}
5834 
5835 		/* Enable boot code */
5836 		boot_state = 1;
5837 		if (emlxs_set_boot_config(hba, boot_state)) {
5838 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5839 			    "boot_code_enable: Unable to set boot config.");
5840 
5841 			return (FC_FAILURE);
5842 		}
5843 
5844 		/* Now read the boot config again to verify */
5845 		if (emlxs_get_boot_config(hba, &boot_state)) {
5846 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5847 			    "boot_code_enable: Unable to get boot config.");
5848 
5849 			return (FC_FAILURE);
5850 		}
5851 
5852 		/* return the result */
5853 		return ((boot_state != 0) ? FC_SUCCESS : FC_FAILURE);
5854 	} else {
5855 		/* Read the wakeup parms */
5856 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 0)) {
5857 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5858 			    "boot_code_enable: Unable to read wake up parms.");
5859 
5860 			return (FC_FAILURE);
5861 		}
5862 
5863 		/* Check if boot code is already enabled */
5864 		if (hba->wakeup_parms.u0.boot_bios_id.Type == BOOT_BIOS) {
5865 			return (FC_SUCCESS);
5866 		}
5867 
5868 		if (!(hba->model_info.chip &
5869 		    (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP))) {
5870 			if (hba->wakeup_parms.u1.EROM_prog_id.Type
5871 			    != BOOT_BIOS) {
5872 				return (EMLXS_NO_BOOT_CODE);
5873 			}
5874 
5875 			/* Update the parms with the boot image id */
5876 			/* Don't load the EROM this time */
5877 			(void) emlxs_update_boot_wakeup_parms(hba,
5878 			    &hba->wakeup_parms,
5879 			    &hba->wakeup_parms.u1.EROM_prog_id, 0);
5880 		} else { /* (EMLXS_DRAGONFLY_CHIP | EMLXS_CENTAUR_CHIP) */
5881 
5882 			count = emlxs_get_load_list(hba, load_list);
5883 
5884 			if (!count) {
5885 				return (FC_FAILURE);
5886 			}
5887 
5888 			/* Scan load list for a boot image */
5889 			for (i = 0; i < count; i++) {
5890 				if (load_list[i].Type == BOOT_BIOS) {
5891 					/*
5892 					 * Update the parms with boot image id
5893 					 * Don't load the EROM this time
5894 					 */
5895 					(void) emlxs_update_boot_wakeup_parms(
5896 					    hba, &hba->wakeup_parms,
5897 					    &load_list[i], 0);
5898 
5899 					break;
5900 				}
5901 			}
5902 
5903 			if (i == count) {
5904 				return (EMLXS_NO_BOOT_CODE);
5905 			}
5906 		}
5907 
5908 		/* Now read the parms again to verify */
5909 		(void) emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1);
5910 		emlxs_decode_version(hba->wakeup_parms.u0.boot_bios_wd[0],
5911 		    vpd->boot_version, sizeof (vpd->boot_version));
5912 		/* (void) strcpy(vpd->fcode_version, vpd->boot_version); */
5913 
5914 		/* return the result */
5915 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5916 		    FC_SUCCESS : FC_FAILURE);
5917 	}
5918 
5919 } /* emlxs_boot_code_enable() */
5920 
5921 
5922 
5923 extern int32_t
emlxs_boot_code_state(emlxs_hba_t * hba)5924 emlxs_boot_code_state(emlxs_hba_t *hba)
5925 {
5926 	emlxs_port_t *port = &PPORT;
5927 	uint8_t boot_state = 0;
5928 
5929 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
5930 		return (FC_SUCCESS);
5931 	}
5932 
5933 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
5934 		/* Read Boot Config */
5935 		if (emlxs_get_boot_config(hba, &boot_state)) {
5936 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5937 			    "boot_code_state: Unable to read boot config.");
5938 
5939 			return (FC_FAILURE);
5940 		}
5941 
5942 		return ((boot_state != 0) ? FC_SUCCESS : FC_FAILURE);
5943 	} else {
5944 		/* Read the wakeup parms */
5945 		if (emlxs_read_wakeup_parms(hba, &hba->wakeup_parms, 1)) {
5946 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sfs_debug_msg,
5947 			    "boot_code_state: Unable to read wake up parms.");
5948 
5949 			return (FC_FAILURE);
5950 		}
5951 
5952 		/* return the result */
5953 		return ((hba->wakeup_parms.u0.boot_bios_wd[0] != 0) ?
5954 		    FC_SUCCESS : FC_FAILURE);
5955 	}
5956 
5957 } /* emlxs_boot_code_state() */
5958