1*03831d35Sstevel /*
2*03831d35Sstevel * CDDL HEADER START
3*03831d35Sstevel *
4*03831d35Sstevel * The contents of this file are subject to the terms of the
5*03831d35Sstevel * Common Development and Distribution License (the "License").
6*03831d35Sstevel * You may not use this file except in compliance with the License.
7*03831d35Sstevel *
8*03831d35Sstevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*03831d35Sstevel * or http://www.opensolaris.org/os/licensing.
10*03831d35Sstevel * See the License for the specific language governing permissions
11*03831d35Sstevel * and limitations under the License.
12*03831d35Sstevel *
13*03831d35Sstevel * When distributing Covered Code, include this CDDL HEADER in each
14*03831d35Sstevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*03831d35Sstevel * If applicable, add the following below this CDDL HEADER, with the
16*03831d35Sstevel * fields enclosed by brackets "[]" replaced with your own identifying
17*03831d35Sstevel * information: Portions Copyright [yyyy] [name of copyright owner]
18*03831d35Sstevel *
19*03831d35Sstevel * CDDL HEADER END
20*03831d35Sstevel */
21*03831d35Sstevel /*
22*03831d35Sstevel * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*03831d35Sstevel * Use is subject to license terms.
24*03831d35Sstevel */
25*03831d35Sstevel
26*03831d35Sstevel #pragma ident "%Z%%M% %I% %E% SMI"
27*03831d35Sstevel
28*03831d35Sstevel /*
29*03831d35Sstevel * download.c: support to the scadm download option (download service
30*03831d35Sstevel * processor firmware)
31*03831d35Sstevel */
32*03831d35Sstevel
33*03831d35Sstevel #include <libintl.h>
34*03831d35Sstevel #include <stdio.h>
35*03831d35Sstevel #include <string.h>
36*03831d35Sstevel #include <time.h> /* required by rsc.h */
37*03831d35Sstevel
38*03831d35Sstevel #include "adm.h"
39*03831d35Sstevel #include "librsc.h"
40*03831d35Sstevel #include "smq.h"
41*03831d35Sstevel
42*03831d35Sstevel
43*03831d35Sstevel extern smq_t ADM_bpMsgQueue;
44*03831d35Sstevel extern smq_msg_t ADM_bpMsgBuffer[ADM_BP_BUFF_SIZE];
45*03831d35Sstevel
46*03831d35Sstevel static void usage();
47*03831d35Sstevel
48*03831d35Sstevel
49*03831d35Sstevel void
ADM_Process_download(int argc,char * argv[])50*03831d35Sstevel ADM_Process_download(int argc, char *argv[])
51*03831d35Sstevel {
52*03831d35Sstevel int BootRetry;
53*03831d35Sstevel uint8_t DownloadLocation;
54*03831d35Sstevel static bp_msg_t Message;
55*03831d35Sstevel static struct timespec Timeout;
56*03831d35Sstevel char *Filename;
57*03831d35Sstevel FILE *FilePtr;
58*03831d35Sstevel timestruc_t Delay;
59*03831d35Sstevel int i, err;
60*03831d35Sstevel int retry;
61*03831d35Sstevel int bootOpt;
62*03831d35Sstevel
63*03831d35Sstevel if ((argc != 3) && (argc != 4)) {
64*03831d35Sstevel usage();
65*03831d35Sstevel exit(-1);
66*03831d35Sstevel }
67*03831d35Sstevel
68*03831d35Sstevel if (argc == 4) {
69*03831d35Sstevel if (strcasecmp(argv[2], "boot") != 0) {
70*03831d35Sstevel usage();
71*03831d35Sstevel exit(-1);
72*03831d35Sstevel }
73*03831d35Sstevel Filename = argv[3];
74*03831d35Sstevel DownloadLocation = BP_DAT2_FLASH_BOOT;
75*03831d35Sstevel bootOpt = 1;
76*03831d35Sstevel } else { /* no [boot] option */
77*03831d35Sstevel
78*03831d35Sstevel Filename = argv[2];
79*03831d35Sstevel DownloadLocation = BP_DAT2_FLASH_MAIN;
80*03831d35Sstevel bootOpt = 0;
81*03831d35Sstevel }
82*03831d35Sstevel
83*03831d35Sstevel if ((FilePtr = fopen(Filename, "r")) == NULL) {
84*03831d35Sstevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
85*03831d35Sstevel gettext("scadm: file could not be opened"), Filename);
86*03831d35Sstevel exit(-1);
87*03831d35Sstevel }
88*03831d35Sstevel
89*03831d35Sstevel
90*03831d35Sstevel /* Verify file is s-record */
91*03831d35Sstevel if (ADM_Valid_srecord(FilePtr) != 0) {
92*03831d35Sstevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
93*03831d35Sstevel gettext("scadm: file not a valid s-record"), Filename);
94*03831d35Sstevel exit(-1);
95*03831d35Sstevel }
96*03831d35Sstevel
97*03831d35Sstevel /*
98*03831d35Sstevel * Don't call rscp_start() because SC may still be in the
99*03831d35Sstevel * boot monitor. The boot monitor will not respond to
100*03831d35Sstevel * rscp_start()
101*03831d35Sstevel */
102*03831d35Sstevel
103*03831d35Sstevel /*
104*03831d35Sstevel * Initialize Message Queue used between ADM_Callback and
105*03831d35Sstevel * ADM_Boot_recv(). ADM_Callback is called from seperate thread.
106*03831d35Sstevel */
107*03831d35Sstevel if (smq_init(&ADM_bpMsgQueue, ADM_bpMsgBuffer,
108*03831d35Sstevel ADM_BP_BUFF_SIZE) != 0) {
109*03831d35Sstevel
110*03831d35Sstevel (void) fprintf(stderr, "\n%s\n\n",
111*03831d35Sstevel gettext("scadm: ERROR, unable to setup message queue"));
112*03831d35Sstevel exit(-1);
113*03831d35Sstevel }
114*03831d35Sstevel
115*03831d35Sstevel /* Initialize callback for Boot Monitor RX */
116*03831d35Sstevel if (rscp_register_bpmsg_cb(ADM_Callback) != 0) {
117*03831d35Sstevel (void) fprintf(stderr, "\n%s\n\n",
118*03831d35Sstevel gettext("scadm: ERROR, callback init failed"));
119*03831d35Sstevel exit(-1);
120*03831d35Sstevel }
121*03831d35Sstevel
122*03831d35Sstevel BootRetry = ADM_BOOT_RETRY;
123*03831d35Sstevel while (BootRetry > 0) {
124*03831d35Sstevel
125*03831d35Sstevel /*
126*03831d35Sstevel * Initialize Message each time because this structure is reused
127*03831d35Sstevel * during receive. Since this operation is not time critical,
128*03831d35Sstevel * this is not a concern
129*03831d35Sstevel */
130*03831d35Sstevel Message.cmd = BP_OBP_BOOTINIT;
131*03831d35Sstevel Message.dat1 = 0;
132*03831d35Sstevel Message.dat2 = DownloadLocation;
133*03831d35Sstevel rscp_send_bpmsg(&Message);
134*03831d35Sstevel
135*03831d35Sstevel /*
136*03831d35Sstevel * Initialize Timeout each time just to be robust. Since this
137*03831d35Sstevel * operation is not time critical, this is not a concern.
138*03831d35Sstevel */
139*03831d35Sstevel Timeout.tv_nsec = 0;
140*03831d35Sstevel Timeout.tv_sec = ADM_BOOT_INIT_TIMEOUT;
141*03831d35Sstevel
142*03831d35Sstevel /* If we timeout, decrement BootRetry and try again */
143*03831d35Sstevel if (ADM_Boot_recv(&Message, &Timeout) != 0) {
144*03831d35Sstevel
145*03831d35Sstevel /* We got a timeout */
146*03831d35Sstevel BootRetry = BootRetry - 1;
147*03831d35Sstevel continue;
148*03831d35Sstevel } else {
149*03831d35Sstevel
150*03831d35Sstevel /* we got a message back, see what it is */
151*03831d35Sstevel if ((Message.cmd != BP_RSC_BOOTACK) ||
152*03831d35Sstevel (Message.dat1 != BP_DAT1_BOOTINIT_ACK)) {
153*03831d35Sstevel
154*03831d35Sstevel ADM_Display_download_error(Message.cmd,
155*03831d35Sstevel Message.dat1);
156*03831d35Sstevel exit(-1);
157*03831d35Sstevel }
158*03831d35Sstevel
159*03831d35Sstevel /*
160*03831d35Sstevel * We got a valid acknowledge, break out of loop and
161*03831d35Sstevel * start to download s-record
162*03831d35Sstevel */
163*03831d35Sstevel break;
164*03831d35Sstevel }
165*03831d35Sstevel }
166*03831d35Sstevel
167*03831d35Sstevel /* See if we ever got a response */
168*03831d35Sstevel if (BootRetry <= 0) {
169*03831d35Sstevel (void) fprintf(stderr, "\n%s\n\n",
170*03831d35Sstevel gettext("scadm: SC did not respond during boot "
171*03831d35Sstevel "initialization"));
172*03831d35Sstevel exit(-1);
173*03831d35Sstevel }
174*03831d35Sstevel
175*03831d35Sstevel /* Download s-record */
176*03831d35Sstevel if (ADM_Send_file(FilePtr) != 0) {
177*03831d35Sstevel (void) fprintf(stderr, "\n%s - \"%s\"\n\n",
178*03831d35Sstevel gettext("scadm: Error downloading file"), Filename);
179*03831d35Sstevel exit(-1);
180*03831d35Sstevel }
181*03831d35Sstevel
182*03831d35Sstevel /* wait a second for BootMonitor to catch up */
183*03831d35Sstevel Delay.tv_nsec = 0;
184*03831d35Sstevel Delay.tv_sec = 1;
185*03831d35Sstevel (void) nanosleep(&Delay, NULL);
186*03831d35Sstevel
187*03831d35Sstevel /* Send Reset boot protocol message to reboot SC */
188*03831d35Sstevel Message.cmd = BP_OBP_RESET;
189*03831d35Sstevel Message.dat1 = 0;
190*03831d35Sstevel Message.dat2 = 0;
191*03831d35Sstevel rscp_send_bpmsg(&Message);
192*03831d35Sstevel
193*03831d35Sstevel /* Cleanup */
194*03831d35Sstevel rscp_unregister_bpmsg_cb(ADM_Callback);
195*03831d35Sstevel (void) smq_destroy(&ADM_bpMsgQueue);
196*03831d35Sstevel (void) fclose(FilePtr);
197*03831d35Sstevel
198*03831d35Sstevel (void) printf("%s\n\n", gettext("Download completed successfully"));
199*03831d35Sstevel
200*03831d35Sstevel (void) printf("%s\n\n", gettext("Please wait for verification"));
201*03831d35Sstevel
202*03831d35Sstevel /*
203*03831d35Sstevel * scadm cannot tell if the SC successfully verified the
204*03831d35Sstevel * download or not, but instead attempts to send a
205*03831d35Sstevel * status message (up to 60 times) and assumes proper
206*03831d35Sstevel * operation when sucessfully sent.
207*03831d35Sstevel *
208*03831d35Sstevel * When the boot option is used, the SC may hang after
209*03831d35Sstevel * resetting itself (after it sucessfully downloads and
210*03831d35Sstevel * verifies the boot file). To work around this, scadm
211*03831d35Sstevel * will (1) do a hard reset and pause for 10 seconds
212*03831d35Sstevel * (2) retry the sending of status messages.
213*03831d35Sstevel */
214*03831d35Sstevel
215*03831d35Sstevel retry = 0;
216*03831d35Sstevel do {
217*03831d35Sstevel if (retry == 1) {
218*03831d35Sstevel /* reset the SC before retrying */
219*03831d35Sstevel if (rsc_nmi() != 0) {
220*03831d35Sstevel (void) fprintf(stderr, "\n%s\n\n",
221*03831d35Sstevel gettext(
222*03831d35Sstevel "scadm: Unable to reset SC hardware"));
223*03831d35Sstevel exit(-1);
224*03831d35Sstevel }
225*03831d35Sstevel /* delay while SC resets */
226*03831d35Sstevel Delay.tv_nsec = 0;
227*03831d35Sstevel Delay.tv_sec = ADM_BOOT_LOAD_TIMEOUT;
228*03831d35Sstevel (void) nanosleep(&Delay, NULL);
229*03831d35Sstevel }
230*03831d35Sstevel
231*03831d35Sstevel for (i = 0; i < 60; i++) {
232*03831d35Sstevel rscp_msg_t msg;
233*03831d35Sstevel msg.type = DP_RSC_STATUS;
234*03831d35Sstevel msg.len = 0;
235*03831d35Sstevel msg.data = NULL;
236*03831d35Sstevel
237*03831d35Sstevel (void) printf("%s", gettext("."));
238*03831d35Sstevel (void) fflush(stdout);
239*03831d35Sstevel
240*03831d35Sstevel err = rscp_send(&msg);
241*03831d35Sstevel if (err == 0)
242*03831d35Sstevel break;
243*03831d35Sstevel }
244*03831d35Sstevel if (err == 0)
245*03831d35Sstevel break;
246*03831d35Sstevel retry++;
247*03831d35Sstevel } while (bootOpt && (retry < 2));
248*03831d35Sstevel if (err == 0)
249*03831d35Sstevel (void) printf("\n%s\n\n", gettext("Complete"));
250*03831d35Sstevel else
251*03831d35Sstevel (void) printf("\n%s\n\n", gettext("Error during verification"));
252*03831d35Sstevel }
253*03831d35Sstevel
254*03831d35Sstevel
255*03831d35Sstevel static void
usage()256*03831d35Sstevel usage()
257*03831d35Sstevel {
258*03831d35Sstevel (void) fprintf(stderr, "\n%s\n\n",
259*03831d35Sstevel gettext("USAGE: scadm download [boot] <file>"));
260*03831d35Sstevel }
261