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