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 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * config.c: support for the scadm configlog option (to display the 29 * service processor configuration log) 30 */ 31 32 #include <libintl.h> 33 #include <stdio.h> 34 #include <string.h> 35 #include <time.h> /* required by librsc.h */ 36 #include <limits.h> 37 38 #include "librsc.h" 39 #include "adm.h" 40 41 /* #define DEBUG */ 42 43 void 44 ADM_Process_fru_log(int all) 45 { 46 rscp_msg_t Message; 47 struct timespec Timeout; 48 dp_get_config_log_r_t *rscReply; 49 rsci64 bytes_remaining, seqno; 50 rsci16 request_size, response_size; 51 dp_get_config_log_t rscCmd; 52 53 ADM_Start(); 54 55 /* 56 * Start by sending a zero-length request to ALOM, so that 57 * we can learn the length of the console log. We expect 58 * ALOM to return the length of the entire log. We get 59 * a snapshot of the length of the log here - it may however 60 * continue to grow as we're reading it. We read only as 61 * much of the log as we get in this snapshot. 62 */ 63 rscCmd.start_seq = 0; 64 rscCmd.length = 0; 65 Message.type = DP_GET_CONFIG_LOG; 66 Message.len = sizeof (rscCmd); 67 Message.data = (char *)&rscCmd; 68 ADM_Send(&Message); 69 70 Timeout.tv_nsec = 0; 71 Timeout.tv_sec = ADM_TIMEOUT; 72 ADM_Recv(&Message, &Timeout, 73 DP_GET_CONFIG_LOG_R, sizeof (*rscReply)); 74 75 rscReply = (dp_get_config_log_r_t *)Message.data; 76 77 /* 78 * If we do not want the whole log, and the log is bigger than 79 * the length limit, then fetch just the last ADM_DEFAULT_LOG_LENGTH 80 * bytes from the log. Else just get the whole thing. 81 */ 82 if ((all == 0) && (rscReply->remaining_log_bytes > 83 ADM_DEFAULT_LOG_LENGTH)) { 84 bytes_remaining = ADM_DEFAULT_LOG_LENGTH; 85 seqno = (rscReply->remaining_log_bytes + 86 rscReply->next_seq) - bytes_remaining; 87 } else { 88 bytes_remaining = rscReply->remaining_log_bytes; 89 seqno = rscReply->next_seq; 90 } 91 request_size = sizeof (rscReply->buffer); 92 ADM_Free(&Message); 93 94 /* 95 * Timeout for RSC response. 96 */ 97 Timeout.tv_nsec = 0; 98 Timeout.tv_sec = ADM_TIMEOUT; 99 100 /* 101 * This loop runs as long as there is data in the log, or until 102 * we hit the default limit (above). It's possible that ALOM may 103 * shrink the log - we need to account for this. If ALOM returns 104 * no data, we bail out. 105 */ 106 while (bytes_remaining) { 107 rscCmd.start_seq = seqno; 108 rscCmd.length = (bytes_remaining < request_size) ? 109 bytes_remaining : request_size; 110 Message.type = DP_GET_CONFIG_LOG; 111 Message.len = sizeof (rscCmd); 112 Message.data = (char *)&rscCmd; 113 ADM_Send(&Message); 114 115 ADM_Recv(&Message, &Timeout, 116 DP_GET_CONFIG_LOG_R, sizeof (*rscReply)); 117 118 rscReply = (dp_get_config_log_r_t *)Message.data; 119 120 /* If ALOM returns zero bytes, we're done. */ 121 response_size = rscReply->length; 122 if (response_size == 0) { 123 ADM_Free(&Message); 124 break; 125 } 126 bytes_remaining -= response_size; 127 if (rscReply->remaining_log_bytes < bytes_remaining) { 128 bytes_remaining = rscReply->remaining_log_bytes; 129 } 130 131 /* 132 * If the byte at the original sequence number is no 133 * longer in the log, print a message. 134 */ 135 if (rscReply->next_seq > seqno + response_size) { 136 printf(gettext("\nscadm: lost %d bytes of log data\n"), 137 rscReply->next_seq - (seqno + response_size)); 138 } 139 seqno = rscReply->next_seq; 140 141 /* Print the config log */ 142 if (fwrite(rscReply->buffer, sizeof (char), response_size, 143 stdout) != response_size) { 144 perror(gettext("\ncouldn't write config log buffer" 145 " to stdout")); 146 ADM_Free(&Message); 147 break; 148 } 149 ADM_Free(&Message); 150 } 151 putchar('\n'); 152 } 153