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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * download.c: support to the scadm download option (download service 30 * processor firmware) 31 */ 32 33 #include <libintl.h> 34 #include <stdio.h> 35 #include <string.h> 36 #include <time.h> /* required by rsc.h */ 37 38 #include "adm.h" 39 #include "librsc.h" 40 #include "smq.h" 41 42 43 extern smq_t ADM_bpMsgQueue; 44 extern smq_msg_t ADM_bpMsgBuffer[ADM_BP_BUFF_SIZE]; 45 46 static void usage(); 47 48 49 void 50 ADM_Process_download(int argc, char *argv[]) 51 { 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; 62 63 if ((argc != 3) && (argc != 4)) { 64 usage(); 65 exit(-1); 66 } 67 68 if (argc == 4) { 69 if (strcasecmp(argv[2], "boot") != 0) { 70 usage(); 71 exit(-1); 72 } 73 Filename = argv[3]; 74 DownloadLocation = BP_DAT2_FLASH_BOOT; 75 bootOpt = 1; 76 } else { /* no [boot] option */ 77 78 Filename = argv[2]; 79 DownloadLocation = BP_DAT2_FLASH_MAIN; 80 bootOpt = 0; 81 } 82 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); 87 } 88 89 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); 95 } 96 97 /* 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() 101 */ 102 103 /* 104 * Initialize Message Queue used between ADM_Callback and 105 * ADM_Boot_recv(). ADM_Callback is called from seperate thread. 106 */ 107 if (smq_init(&ADM_bpMsgQueue, ADM_bpMsgBuffer, 108 ADM_BP_BUFF_SIZE) != 0) { 109 110 (void) fprintf(stderr, "\n%s\n\n", 111 gettext("scadm: ERROR, unable to setup message queue")); 112 exit(-1); 113 } 114 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); 120 } 121 122 BootRetry = ADM_BOOT_RETRY; 123 while (BootRetry > 0) { 124 125 /* 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 129 */ 130 Message.cmd = BP_OBP_BOOTINIT; 131 Message.dat1 = 0; 132 Message.dat2 = DownloadLocation; 133 rscp_send_bpmsg(&Message); 134 135 /* 136 * Initialize Timeout each time just to be robust. Since this 137 * operation is not time critical, this is not a concern. 138 */ 139 Timeout.tv_nsec = 0; 140 Timeout.tv_sec = ADM_BOOT_INIT_TIMEOUT; 141 142 /* If we timeout, decrement BootRetry and try again */ 143 if (ADM_Boot_recv(&Message, &Timeout) != 0) { 144 145 /* We got a timeout */ 146 BootRetry = BootRetry - 1; 147 continue; 148 } else { 149 150 /* we got a message back, see what it is */ 151 if ((Message.cmd != BP_RSC_BOOTACK) || 152 (Message.dat1 != BP_DAT1_BOOTINIT_ACK)) { 153 154 ADM_Display_download_error(Message.cmd, 155 Message.dat1); 156 exit(-1); 157 } 158 159 /* 160 * We got a valid acknowledge, break out of loop and 161 * start to download s-record 162 */ 163 break; 164 } 165 } 166 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); 173 } 174 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); 180 } 181 182 /* wait a second for BootMonitor to catch up */ 183 Delay.tv_nsec = 0; 184 Delay.tv_sec = 1; 185 (void) nanosleep(&Delay, NULL); 186 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); 192 193 /* Cleanup */ 194 rscp_unregister_bpmsg_cb(ADM_Callback); 195 (void) smq_destroy(&ADM_bpMsgQueue); 196 (void) fclose(FilePtr); 197 198 (void) printf("%s\n\n", gettext("Download completed successfully")); 199 200 (void) printf("%s\n\n", gettext("Please wait for verification")); 201 202 /* 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. 207 * 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. 213 */ 214 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); 224 } 225 /* delay while SC resets */ 226 Delay.tv_nsec = 0; 227 Delay.tv_sec = ADM_BOOT_LOAD_TIMEOUT; 228 (void) nanosleep(&Delay, NULL); 229 } 230 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; 236 237 (void) printf("%s", gettext(".")); 238 (void) fflush(stdout); 239 240 err = rscp_send(&msg); 241 if (err == 0) 242 break; 243 } 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")); 252 } 253 254 255 static void 256 usage() 257 { 258 (void) fprintf(stderr, "\n%s\n\n", 259 gettext("USAGE: scadm download [boot] <file>")); 260 } 261