8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / scadm / sparc / mpxu / common / download.c
blob1b52227c17ec675bb2de24380232dee712a5ff58
1 /*
2 * CDDL HEADER START
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.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
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]
19 * CDDL HEADER END
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * download.c: support to the scadm download option (download service
30 * processor firmware)
33 #include <libintl.h>
34 #include <stdio.h>
35 #include <string.h>
36 #include <time.h> /* required by rsc.h */
38 #include "adm.h"
39 #include "librsc.h"
40 #include "smq.h"
43 extern smq_t ADM_bpMsgQueue;
44 extern smq_msg_t ADM_bpMsgBuffer[ADM_BP_BUFF_SIZE];
46 static void usage();
49 void
50 ADM_Process_download(int argc, char *argv[])
52 int BootRetry;
53 uint8_t DownloadLocation;
54 static bp_msg_t Message;
55 static struct timespec Timeout;
56 char *Filename;
57 FILE *FilePtr;
58 timestruc_t Delay;
59 int i, err;
60 int retry;
61 int bootOpt;
63 if ((argc != 3) && (argc != 4)) {
64 usage();
65 exit(-1);
68 if (argc == 4) {
69 if (strcasecmp(argv[2], "boot") != 0) {
70 usage();
71 exit(-1);
73 Filename = argv[3];
74 DownloadLocation = BP_DAT2_FLASH_BOOT;
75 bootOpt = 1;
76 } else { /* no [boot] option */
78 Filename = argv[2];
79 DownloadLocation = BP_DAT2_FLASH_MAIN;
80 bootOpt = 0;
83 if ((FilePtr = fopen(Filename, "r")) == NULL) {
84 (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
85 gettext("scadm: file could not be opened"), Filename);
86 exit(-1);
90 /* Verify file is s-record */
91 if (ADM_Valid_srecord(FilePtr) != 0) {
92 (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
93 gettext("scadm: file not a valid s-record"), Filename);
94 exit(-1);
98 * Don't call rscp_start() because SC may still be in the
99 * boot monitor. The boot monitor will not respond to
100 * rscp_start()
104 * Initialize Message Queue used between ADM_Callback and
105 * ADM_Boot_recv(). ADM_Callback is called from seperate thread.
107 if (smq_init(&ADM_bpMsgQueue, ADM_bpMsgBuffer,
108 ADM_BP_BUFF_SIZE) != 0) {
110 (void) fprintf(stderr, "\n%s\n\n",
111 gettext("scadm: ERROR, unable to setup message queue"));
112 exit(-1);
115 /* Initialize callback for Boot Monitor RX */
116 if (rscp_register_bpmsg_cb(ADM_Callback) != 0) {
117 (void) fprintf(stderr, "\n%s\n\n",
118 gettext("scadm: ERROR, callback init failed"));
119 exit(-1);
122 BootRetry = ADM_BOOT_RETRY;
123 while (BootRetry > 0) {
126 * Initialize Message each time because this structure is reused
127 * during receive. Since this operation is not time critical,
128 * this is not a concern
130 Message.cmd = BP_OBP_BOOTINIT;
131 Message.dat1 = 0;
132 Message.dat2 = DownloadLocation;
133 rscp_send_bpmsg(&Message);
136 * Initialize Timeout each time just to be robust. Since this
137 * operation is not time critical, this is not a concern.
139 Timeout.tv_nsec = 0;
140 Timeout.tv_sec = ADM_BOOT_INIT_TIMEOUT;
142 /* If we timeout, decrement BootRetry and try again */
143 if (ADM_Boot_recv(&Message, &Timeout) != 0) {
145 /* We got a timeout */
146 BootRetry = BootRetry - 1;
147 continue;
148 } else {
150 /* we got a message back, see what it is */
151 if ((Message.cmd != BP_RSC_BOOTACK) ||
152 (Message.dat1 != BP_DAT1_BOOTINIT_ACK)) {
154 ADM_Display_download_error(Message.cmd,
155 Message.dat1);
156 exit(-1);
160 * We got a valid acknowledge, break out of loop and
161 * start to download s-record
163 break;
167 /* See if we ever got a response */
168 if (BootRetry <= 0) {
169 (void) fprintf(stderr, "\n%s\n\n",
170 gettext("scadm: SC did not respond during boot "
171 "initialization"));
172 exit(-1);
175 /* Download s-record */
176 if (ADM_Send_file(FilePtr) != 0) {
177 (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
178 gettext("scadm: Error downloading file"), Filename);
179 exit(-1);
182 /* wait a second for BootMonitor to catch up */
183 Delay.tv_nsec = 0;
184 Delay.tv_sec = 1;
185 (void) nanosleep(&Delay, NULL);
187 /* Send Reset boot protocol message to reboot SC */
188 Message.cmd = BP_OBP_RESET;
189 Message.dat1 = 0;
190 Message.dat2 = 0;
191 rscp_send_bpmsg(&Message);
193 /* Cleanup */
194 rscp_unregister_bpmsg_cb(ADM_Callback);
195 (void) smq_destroy(&ADM_bpMsgQueue);
196 (void) fclose(FilePtr);
198 (void) printf("%s\n\n", gettext("Download completed successfully"));
200 (void) printf("%s\n\n", gettext("Please wait for verification"));
203 * scadm cannot tell if the SC successfully verified the
204 * download or not, but instead attempts to send a
205 * status message (up to 60 times) and assumes proper
206 * operation when sucessfully sent.
208 * When the boot option is used, the SC may hang after
209 * resetting itself (after it sucessfully downloads and
210 * verifies the boot file). To work around this, scadm
211 * will (1) do a hard reset and pause for 10 seconds
212 * (2) retry the sending of status messages.
215 retry = 0;
216 do {
217 if (retry == 1) {
218 /* reset the SC before retrying */
219 if (rsc_nmi() != 0) {
220 (void) fprintf(stderr, "\n%s\n\n",
221 gettext(
222 "scadm: Unable to reset SC hardware"));
223 exit(-1);
225 /* delay while SC resets */
226 Delay.tv_nsec = 0;
227 Delay.tv_sec = ADM_BOOT_LOAD_TIMEOUT;
228 (void) nanosleep(&Delay, NULL);
231 for (i = 0; i < 60; i++) {
232 rscp_msg_t msg;
233 msg.type = DP_RSC_STATUS;
234 msg.len = 0;
235 msg.data = NULL;
237 (void) printf("%s", gettext("."));
238 (void) fflush(stdout);
240 err = rscp_send(&msg);
241 if (err == 0)
242 break;
244 if (err == 0)
245 break;
246 retry++;
247 } while (bootOpt && (retry < 2));
248 if (err == 0)
249 (void) printf("\n%s\n\n", gettext("Complete"));
250 else
251 (void) printf("\n%s\n\n", gettext("Error during verification"));
255 static void
256 usage()
258 (void) fprintf(stderr, "\n%s\n\n",
259 gettext("USAGE: scadm download [boot] <file>"));