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
43 int
ADM_Send_file(FILE * FilePtr)44 ADM_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
163 void
ADM_Display_download_error(int cmd,int dat1)164 ADM_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