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, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2002-2003 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29/*
30 * send_file.c: to support firmware download (get fw S-records from the
31 * user-specified file and send S-records string down to the service processor
32 */
33
34#include <libintl.h>
35#include <stdio.h>
36#include <string.h>
37#include <time.h>
38
39#include "librsc.h"
40#include "adm.h"
41
42
43int
44ADM_Send_file(FILE  *FilePtr)
45{
46	static char		ADM_Line[ADM_LINE_SIZE];
47	static bp_msg_t		Message;
48	static struct timespec	Timeout;
49	int			LinesWritten;
50	int			Status;
51	int			BootRetry;
52	int			LastRecord;
53	long			FileLength = 0L;
54	long			FilePos;
55
56
57	/*
58	 * Determine the length of the file
59	 */
60	if (fseek(FilePtr, 0L, SEEK_END) == 0) {
61		FileLength = ftell(FilePtr);
62		rewind(FilePtr);
63	}
64
65	LinesWritten = 0;
66	LastRecord   = 0;
67	while ((fgets(ADM_Line, ADM_LINE_SIZE, FilePtr) != NULL) &&
68	    (LastRecord == 0)) {
69		if ((ADM_Line[0] == 'S') &&
70		    ((ADM_Line[1] == '7') || (ADM_Line[1] == '8') ||
71		    (ADM_Line[1] == '9'))) {
72			LastRecord = 1;
73		}
74
75		BootRetry = ADM_BOOT_RETRY;
76		while (BootRetry > 0) {
77			if ((Status =
78			    rsc_raw_write(ADM_Line, strlen(ADM_Line))) != 0) {
79				return (Status);
80			}
81
82			/*
83			 * Initialize Timeout each time just to be robust.
84			 * Since this operation is not time critical, this is
85			 * not a concern.
86			 */
87			Timeout.tv_nsec = 0;
88			Timeout.tv_sec  = ADM_BOOT_LOAD_TIMEOUT;
89			/* If we timeout, decrement BootRetry and try again */
90			if ((Status = ADM_Boot_recv(&Message, &Timeout)) != 0) {
91				/* We got a timeout */
92				BootRetry = BootRetry - 1;
93				continue;
94
95			} else {
96
97				/* we got a message back, see what it is */
98				if ((Message.cmd  == BP_RSC_BOOTOK) &&
99				    (Message.dat1 == 0) &&
100				    (Message.dat2 == 0)) {
101
102					LastRecord = 1;
103					break;
104				}
105
106				if ((Message.cmd  != BP_RSC_BOOTACK) ||
107				    (Message.dat1 != BP_DAT1_SRECORD_ACK)) {
108
109					if (Message.dat1 ==
110					    BP_DAT1_SRECORD_NAK) {
111						continue;
112					}
113					ADM_Display_download_error(
114					    (int)Message.cmd,
115					    (int)Message.dat1);
116					exit(-1);
117				}
118
119				/*
120				 * We got a valid acknowledge, break out of
121				 * loop and start to download next s-record
122				 */
123				break;
124			}
125		}
126
127		/* See if we ever got a response */
128		if (BootRetry <= 0) {
129			(void) fprintf(stderr, "\n%s\n\n",
130			    gettext("scadm: SC failed to respond during "
131			    "download"));
132			exit(-1);
133		}
134
135		LinesWritten++;
136		if ((LinesWritten % 100) == 0) {
137			(void) printf(".");
138			(void) fflush(stdout);
139		}
140		if ((LinesWritten % 4000) == 0) {
141			if (FileLength) {
142				/* Show % progress */
143				FilePos = ftell(FilePtr);
144				(void) printf(" (%ld%%)",
145				    (FilePos * 100) / FileLength);
146			}
147			(void) printf("\n");
148			(void) fflush(stdout);
149		}
150	}
151	if ((FileLength) && ((LinesWritten % 4000) != 0)) {
152		/* Show final % progress (should normally be 100%) */
153		FilePos = ftell(FilePtr);
154		(void) printf(" (%ld%%)",
155		    (FilePos * 100) / FileLength);
156	}
157	(void) printf("\n");
158
159	return (0);
160}
161
162
163void
164ADM_Display_download_error(int cmd, int dat1)
165{
166	if (cmd == BP_RSC_BOOTFAIL) {
167		if (dat1 == BP_DAT1_REJECTED) {
168			(void) fprintf(stderr, "\n%s\n\n",
169			    gettext("scadm: download rejected"));
170
171		} else if (dat1 == BP_DAT1_RANGE_ERR) {
172			(void) fprintf(stderr, "\n%s\n\n",
173			    gettext("scadm: download failed, "
174			    "SC reported range error"));
175
176		} else if (dat1 == BP_DAT1_VERIFY_ERR) {
177			(void) fprintf(stderr, "\n%s\n\n",
178			    gettext("scadm: download failed, "
179			    "SC reported verify error"));
180
181		} else if (dat1 == BP_DAT1_ERASE_ERR) {
182			(void) fprintf(stderr, "\n%s\n\n",
183			    gettext("scadm: download failed, "
184			    "SC reported erase error"));
185
186		} else if (dat1 == BP_DAT1_INT_WP_ERR) {
187			(void) fprintf(stderr, "\n%s\n\n",
188			    gettext("scadm: download failed, "
189			    "SC reported int_wp error"));
190
191		} else if (dat1 == BP_DAT1_WP_ERR) {
192			(void) fprintf(stderr, "\n%s\n\n",
193			    gettext("scadm: download failed, "
194			    "SC reported wp error"));
195
196		} else if (dat1 == BP_DAT1_VPP_ERR) {
197			(void) fprintf(stderr, "\n%s\n\n",
198			    gettext("scadm: download failed, "
199			    "SC reported vpp error"));
200		} else {
201			(void) fprintf(stderr, "%s 0x%08x\n",
202			    gettext("scadm: SC returned fatal error"), dat1);
203		}
204	} else if (cmd == BP_RSC_BOOTACK) {
205		if (dat1 == BP_DAT1_SRECORD_ACK) {
206			(void) fprintf(stderr, "\n%s\n\n",
207			    gettext("scadm: download failed"));
208		} else {
209			(void) fprintf(stderr, "%s 0x%08x\n",
210			    gettext("scadm: SC returned fatal error"), dat1);
211		}
212	} else {
213		(void) fprintf(stderr, "%s 0x%08x:0x%08x\n",
214		    gettext("scadm: SC returned unknown error"), cmd, dat1);
215	}
216}
217