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 /* 28 * send_file.c: to support firmware download (get fw S-records from the 29 * user-specified file and send S-records string down to the service processor 30 */ 31 32 #include <libintl.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <time.h> 36 37 #include "librsc.h" 38 #include "adm.h" 39 40 41 int 42 ADM_Send_file(FILE *FilePtr) 43 { 44 static char ADM_Line[ADM_LINE_SIZE]; 45 static bp_msg_t Message; 46 static struct timespec Timeout; 47 int LinesWritten; 48 int Status; 49 int BootRetry; 50 int LastRecord; 51 long FileLength = 0L; 52 long FilePos; 53 54 55 /* 56 * Determine the length of the file 57 */ 58 if (fseek(FilePtr, 0L, SEEK_END) == 0) { 59 FileLength = ftell(FilePtr); 60 rewind(FilePtr); 61 } 62 63 LinesWritten = 0; 64 LastRecord = 0; 65 while ((fgets(ADM_Line, ADM_LINE_SIZE, FilePtr) != NULL) && 66 (LastRecord == 0)) { 67 if ((ADM_Line[0] == 'S') && 68 ((ADM_Line[1] == '7') || (ADM_Line[1] == '8') || 69 (ADM_Line[1] == '9'))) { 70 LastRecord = 1; 71 } 72 73 BootRetry = ADM_BOOT_RETRY; 74 while (BootRetry > 0) { 75 if ((Status = 76 rsc_raw_write(ADM_Line, strlen(ADM_Line))) != 0) { 77 return (Status); 78 } 79 80 /* 81 * Initialize Timeout each time just to be robust. 82 * Since this operation is not time critical, this is 83 * not a concern. 84 */ 85 Timeout.tv_nsec = 0; 86 Timeout.tv_sec = ADM_BOOT_LOAD_TIMEOUT; 87 /* If we timeout, decrement BootRetry and try again */ 88 if ((Status = ADM_Boot_recv(&Message, &Timeout)) != 0) { 89 /* We got a timeout */ 90 BootRetry = BootRetry - 1; 91 continue; 92 93 } else { 94 95 /* we got a message back, see what it is */ 96 if ((Message.cmd == BP_RSC_BOOTOK) && 97 (Message.dat1 == 0) && 98 (Message.dat2 == 0)) { 99 100 LastRecord = 1; 101 break; 102 } 103 104 if ((Message.cmd != BP_RSC_BOOTACK) || 105 (Message.dat1 != BP_DAT1_SRECORD_ACK)) { 106 107 if (Message.dat1 == 108 BP_DAT1_SRECORD_NAK) { 109 continue; 110 } 111 ADM_Display_download_error( 112 (int)Message.cmd, 113 (int)Message.dat1); 114 exit(-1); 115 } 116 117 /* 118 * We got a valid acknowledge, break out of 119 * loop and start to download next s-record 120 */ 121 break; 122 } 123 } 124 125 /* See if we ever got a response */ 126 if (BootRetry <= 0) { 127 (void) fprintf(stderr, "\n%s\n\n", 128 gettext("scadm: SC failed to respond during " 129 "download")); 130 exit(-1); 131 } 132 133 LinesWritten++; 134 if ((LinesWritten % 100) == 0) { 135 (void) printf("."); 136 (void) fflush(stdout); 137 } 138 if ((LinesWritten % 4000) == 0) { 139 if (FileLength) { 140 /* Show % progress */ 141 FilePos = ftell(FilePtr); 142 (void) printf(" (%ld%%)", 143 (FilePos * 100) / FileLength); 144 } 145 (void) printf("\n"); 146 (void) fflush(stdout); 147 } 148 } 149 if ((FileLength) && ((LinesWritten % 4000) != 0)) { 150 /* Show final % progress (should normally be 100%) */ 151 FilePos = ftell(FilePtr); 152 (void) printf(" (%ld%%)", 153 (FilePos * 100) / FileLength); 154 } 155 (void) printf("\n"); 156 157 return (0); 158 } 159 160 161 void 162 ADM_Display_download_error(int cmd, int dat1) 163 { 164 if (cmd == BP_RSC_BOOTFAIL) { 165 if (dat1 == BP_DAT1_REJECTED) { 166 (void) fprintf(stderr, "\n%s\n\n", 167 gettext("scadm: download rejected")); 168 169 } else if (dat1 == BP_DAT1_RANGE_ERR) { 170 (void) fprintf(stderr, "\n%s\n\n", 171 gettext("scadm: download failed, " 172 "SC reported range error")); 173 174 } else if (dat1 == BP_DAT1_VERIFY_ERR) { 175 (void) fprintf(stderr, "\n%s\n\n", 176 gettext("scadm: download failed, " 177 "SC reported verify error")); 178 179 } else if (dat1 == BP_DAT1_ERASE_ERR) { 180 (void) fprintf(stderr, "\n%s\n\n", 181 gettext("scadm: download failed, " 182 "SC reported erase error")); 183 184 } else if (dat1 == BP_DAT1_INT_WP_ERR) { 185 (void) fprintf(stderr, "\n%s\n\n", 186 gettext("scadm: download failed, " 187 "SC reported int_wp error")); 188 189 } else if (dat1 == BP_DAT1_WP_ERR) { 190 (void) fprintf(stderr, "\n%s\n\n", 191 gettext("scadm: download failed, " 192 "SC reported wp error")); 193 194 } else if (dat1 == BP_DAT1_VPP_ERR) { 195 (void) fprintf(stderr, "\n%s\n\n", 196 gettext("scadm: download failed, " 197 "SC reported vpp error")); 198 } else { 199 (void) fprintf(stderr, "%s 0x%08x\n", 200 gettext("scadm: SC returned fatal error"), dat1); 201 } 202 } else if (cmd == BP_RSC_BOOTACK) { 203 if (dat1 == BP_DAT1_SRECORD_ACK) { 204 (void) fprintf(stderr, "\n%s\n\n", 205 gettext("scadm: download failed")); 206 } else { 207 (void) fprintf(stderr, "%s 0x%08x\n", 208 gettext("scadm: SC returned fatal error"), dat1); 209 } 210 } else { 211 (void) fprintf(stderr, "%s 0x%08x:0x%08x\n", 212 gettext("scadm: SC returned unknown error"), cmd, dat1); 213 } 214 } 215