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