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 /*
28  * send_file.c: to support firmware download (get fw S-records from the
29  * user-specified file and send S-records string down to the service processor
30  */
31 
32 #include <libintl.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <time.h>
36 
37 #include "librsc.h"
38 #include "adm.h"
39 
40 
41 int
ADM_Send_file(FILE * FilePtr)42 ADM_Send_file(FILE  *FilePtr)
43 {
44 	static char		ADM_Line[ADM_LINE_SIZE];
45 	static bp_msg_t		Message;
46 	static struct timespec	Timeout;
47 	int			LinesWritten;
48 	int			Status;
49 	int			BootRetry;
50 	int			LastRecord;
51 	long			FileLength = 0L;
52 	long			FilePos;
53 
54 
55 	/*
56 	 * Determine the length of the file
57 	 */
58 	if (fseek(FilePtr, 0L, SEEK_END) == 0) {
59 		FileLength = ftell(FilePtr);
60 		rewind(FilePtr);
61 	}
62 
63 	LinesWritten = 0;
64 	LastRecord   = 0;
65 	while ((fgets(ADM_Line, ADM_LINE_SIZE, FilePtr) != NULL) &&
66 	    (LastRecord == 0)) {
67 		if ((ADM_Line[0] == 'S') &&
68 		    ((ADM_Line[1] == '7') || (ADM_Line[1] == '8') ||
69 		    (ADM_Line[1] == '9'))) {
70 			LastRecord = 1;
71 		}
72 
73 		BootRetry = ADM_BOOT_RETRY;
74 		while (BootRetry > 0) {
75 			if ((Status =
76 			    rsc_raw_write(ADM_Line, strlen(ADM_Line))) != 0) {
77 				return (Status);
78 			}
79 
80 			/*
81 			 * Initialize Timeout each time just to be robust.
82 			 * Since this operation is not time critical, this is
83 			 * not a concern.
84 			 */
85 			Timeout.tv_nsec = 0;
86 			Timeout.tv_sec  = ADM_BOOT_LOAD_TIMEOUT;
87 			/* If we timeout, decrement BootRetry and try again */
88 			if ((Status = ADM_Boot_recv(&Message, &Timeout)) != 0) {
89 				/* We got a timeout */
90 				BootRetry = BootRetry - 1;
91 				continue;
92 
93 			} else {
94 
95 				/* we got a message back, see what it is */
96 				if ((Message.cmd  == BP_RSC_BOOTOK) &&
97 				    (Message.dat1 == 0) &&
98 				    (Message.dat2 == 0)) {
99 
100 					LastRecord = 1;
101 					break;
102 				}
103 
104 				if ((Message.cmd  != BP_RSC_BOOTACK) ||
105 				    (Message.dat1 != BP_DAT1_SRECORD_ACK)) {
106 
107 					if (Message.dat1 ==
108 					    BP_DAT1_SRECORD_NAK) {
109 						continue;
110 					}
111 					ADM_Display_download_error(
112 					    (int)Message.cmd,
113 					    (int)Message.dat1);
114 					exit(-1);
115 				}
116 
117 				/*
118 				 * We got a valid acknowledge, break out of
119 				 * loop and start to download next s-record
120 				 */
121 				break;
122 			}
123 		}
124 
125 		/* See if we ever got a response */
126 		if (BootRetry <= 0) {
127 			(void) fprintf(stderr, "\n%s\n\n",
128 			    gettext("scadm: SC failed to respond during "
129 			    "download"));
130 			exit(-1);
131 		}
132 
133 		LinesWritten++;
134 		if ((LinesWritten % 100) == 0) {
135 			(void) printf(".");
136 			(void) fflush(stdout);
137 		}
138 		if ((LinesWritten % 4000) == 0) {
139 			if (FileLength) {
140 				/* Show % progress */
141 				FilePos = ftell(FilePtr);
142 				(void) printf(" (%ld%%)",
143 				    (FilePos * 100) / FileLength);
144 			}
145 			(void) printf("\n");
146 			(void) fflush(stdout);
147 		}
148 	}
149 	if ((FileLength) && ((LinesWritten % 4000) != 0)) {
150 		/* Show final % progress (should normally be 100%) */
151 		FilePos = ftell(FilePtr);
152 		(void) printf(" (%ld%%)",
153 		    (FilePos * 100) / FileLength);
154 	}
155 	(void) printf("\n");
156 
157 	return (0);
158 }
159 
160 
161 void
ADM_Display_download_error(int cmd,int dat1)162 ADM_Display_download_error(int cmd, int dat1)
163 {
164 	if (cmd == BP_RSC_BOOTFAIL) {
165 		if (dat1 == BP_DAT1_REJECTED) {
166 			(void) fprintf(stderr, "\n%s\n\n",
167 			    gettext("scadm: download rejected"));
168 
169 		} else if (dat1 == BP_DAT1_RANGE_ERR) {
170 			(void) fprintf(stderr, "\n%s\n\n",
171 			    gettext("scadm: download failed, "
172 			    "SC reported range error"));
173 
174 		} else if (dat1 == BP_DAT1_VERIFY_ERR) {
175 			(void) fprintf(stderr, "\n%s\n\n",
176 			    gettext("scadm: download failed, "
177 			    "SC reported verify error"));
178 
179 		} else if (dat1 == BP_DAT1_ERASE_ERR) {
180 			(void) fprintf(stderr, "\n%s\n\n",
181 			    gettext("scadm: download failed, "
182 			    "SC reported erase error"));
183 
184 		} else if (dat1 == BP_DAT1_INT_WP_ERR) {
185 			(void) fprintf(stderr, "\n%s\n\n",
186 			    gettext("scadm: download failed, "
187 			    "SC reported int_wp error"));
188 
189 		} else if (dat1 == BP_DAT1_WP_ERR) {
190 			(void) fprintf(stderr, "\n%s\n\n",
191 			    gettext("scadm: download failed, "
192 			    "SC reported wp error"));
193 
194 		} else if (dat1 == BP_DAT1_VPP_ERR) {
195 			(void) fprintf(stderr, "\n%s\n\n",
196 			    gettext("scadm: download failed, "
197 			    "SC reported vpp error"));
198 		} else {
199 			(void) fprintf(stderr, "%s 0x%08x\n",
200 			    gettext("scadm: SC returned fatal error"), dat1);
201 		}
202 	} else if (cmd == BP_RSC_BOOTACK) {
203 		if (dat1 == BP_DAT1_SRECORD_ACK) {
204 			(void) fprintf(stderr, "\n%s\n\n",
205 			    gettext("scadm: download failed"));
206 		} else {
207 			(void) fprintf(stderr, "%s 0x%08x\n",
208 			    gettext("scadm: SC returned fatal error"), dat1);
209 		}
210 	} else {
211 		(void) fprintf(stderr, "%s 0x%08x:0x%08x\n",
212 		    gettext("scadm: SC returned unknown error"), cmd, dat1);
213 	}
214 }
215