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 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 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