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