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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * send_file.c: to support firmware download (get fw S-records from the 31 * user-specified file and send S-records string down to the service processor 32 */ 33 34 #include <libintl.h> 35 #include <stdio.h> 36 #include <string.h> 37 #include <time.h> 38 39 #include "librsc.h" 40 #include "adm.h" 41 42 43 int 44 ADM_Send_file(FILE *FilePtr) 45 { 46 static char ADM_Line[ADM_LINE_SIZE]; 47 static bp_msg_t Message; 48 static struct timespec Timeout; 49 int LinesWritten; 50 int Status; 51 int BootRetry; 52 int LastRecord; 53 long FileLength = 0L; 54 long FilePos; 55 56 57 /* 58 * Determine the length of the file 59 */ 60 if (fseek(FilePtr, 0L, SEEK_END) == 0) { 61 FileLength = ftell(FilePtr); 62 rewind(FilePtr); 63 } 64 65 LinesWritten = 0; 66 LastRecord = 0; 67 while ((fgets(ADM_Line, ADM_LINE_SIZE, FilePtr) != NULL) && 68 (LastRecord == 0)) { 69 if ((ADM_Line[0] == 'S') && 70 ((ADM_Line[1] == '7') || (ADM_Line[1] == '8') || 71 (ADM_Line[1] == '9'))) { 72 LastRecord = 1; 73 } 74 75 BootRetry = ADM_BOOT_RETRY; 76 while (BootRetry > 0) { 77 if ((Status = 78 rsc_raw_write(ADM_Line, strlen(ADM_Line))) != 0) { 79 return (Status); 80 } 81 82 /* 83 * Initialize Timeout each time just to be robust. 84 * Since this operation is not time critical, this is 85 * not a concern. 86 */ 87 Timeout.tv_nsec = 0; 88 Timeout.tv_sec = ADM_BOOT_LOAD_TIMEOUT; 89 /* If we timeout, decrement BootRetry and try again */ 90 if ((Status = ADM_Boot_recv(&Message, &Timeout)) != 0) { 91 /* We got a timeout */ 92 BootRetry = BootRetry - 1; 93 continue; 94 95 } else { 96 97 /* we got a message back, see what it is */ 98 if ((Message.cmd == BP_RSC_BOOTOK) && 99 (Message.dat1 == 0) && 100 (Message.dat2 == 0)) { 101 102 LastRecord = 1; 103 break; 104 } 105 106 if ((Message.cmd != BP_RSC_BOOTACK) || 107 (Message.dat1 != BP_DAT1_SRECORD_ACK)) { 108 109 if (Message.dat1 == 110 BP_DAT1_SRECORD_NAK) { 111 continue; 112 } 113 ADM_Display_download_error( 114 (int)Message.cmd, 115 (int)Message.dat1); 116 exit(-1); 117 } 118 119 /* 120 * We got a valid acknowledge, break out of 121 * loop and start to download next s-record 122 */ 123 break; 124 } 125 } 126 127 /* See if we ever got a response */ 128 if (BootRetry <= 0) { 129 (void) fprintf(stderr, "\n%s\n\n", 130 gettext("scadm: SC failed to respond during " 131 "download")); 132 exit(-1); 133 } 134 135 LinesWritten++; 136 if ((LinesWritten % 100) == 0) { 137 (void) printf("."); 138 (void) fflush(stdout); 139 } 140 if ((LinesWritten % 4000) == 0) { 141 if (FileLength) { 142 /* Show % progress */ 143 FilePos = ftell(FilePtr); 144 (void) printf(" (%ld%%)", 145 (FilePos * 100) / FileLength); 146 } 147 (void) printf("\n"); 148 (void) fflush(stdout); 149 } 150 } 151 if ((FileLength) && ((LinesWritten % 4000) != 0)) { 152 /* Show final % progress (should normally be 100%) */ 153 FilePos = ftell(FilePtr); 154 (void) printf(" (%ld%%)", 155 (FilePos * 100) / FileLength); 156 } 157 (void) printf("\n"); 158 159 return (0); 160 } 161 162 163 void 164 ADM_Display_download_error(int cmd, int dat1) 165 { 166 if (cmd == BP_RSC_BOOTFAIL) { 167 if (dat1 == BP_DAT1_REJECTED) { 168 (void) fprintf(stderr, "\n%s\n\n", 169 gettext("scadm: download rejected")); 170 171 } else if (dat1 == BP_DAT1_RANGE_ERR) { 172 (void) fprintf(stderr, "\n%s\n\n", 173 gettext("scadm: download failed, " 174 "SC reported range error")); 175 176 } else if (dat1 == BP_DAT1_VERIFY_ERR) { 177 (void) fprintf(stderr, "\n%s\n\n", 178 gettext("scadm: download failed, " 179 "SC reported verify error")); 180 181 } else if (dat1 == BP_DAT1_ERASE_ERR) { 182 (void) fprintf(stderr, "\n%s\n\n", 183 gettext("scadm: download failed, " 184 "SC reported erase error")); 185 186 } else if (dat1 == BP_DAT1_INT_WP_ERR) { 187 (void) fprintf(stderr, "\n%s\n\n", 188 gettext("scadm: download failed, " 189 "SC reported int_wp error")); 190 191 } else if (dat1 == BP_DAT1_WP_ERR) { 192 (void) fprintf(stderr, "\n%s\n\n", 193 gettext("scadm: download failed, " 194 "SC reported wp error")); 195 196 } else if (dat1 == BP_DAT1_VPP_ERR) { 197 (void) fprintf(stderr, "\n%s\n\n", 198 gettext("scadm: download failed, " 199 "SC reported vpp error")); 200 } else { 201 (void) fprintf(stderr, "%s 0x%08x\n", 202 gettext("scadm: SC returned fatal error"), dat1); 203 } 204 } else if (cmd == BP_RSC_BOOTACK) { 205 if (dat1 == BP_DAT1_SRECORD_ACK) { 206 (void) fprintf(stderr, "\n%s\n\n", 207 gettext("scadm: download failed")); 208 } else { 209 (void) fprintf(stderr, "%s 0x%08x\n", 210 gettext("scadm: SC returned fatal error"), dat1); 211 } 212 } else { 213 (void) fprintf(stderr, "%s 0x%08x:0x%08x\n", 214 gettext("scadm: SC returned unknown error"), cmd, dat1); 215 } 216 } 217