/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * consolelog.c: support for the scadm consolelog option (to display the * service processor console log) */ #include #include #include #include /* required by librsc.h */ #include #include "librsc.h" #include "adm.h" /* #define DEBUG */ void ADM_Process_console_log(int all) { rscp_msg_t Message; struct timespec Timeout; dp_get_console_log_r_t *rscReply; rsci64 bytes_remaining, seqno; rsci16 request_size, response_size; dp_get_console_log_t rscCmd; ADM_Start(); /* * Start by sending a zero-length request to ALOM, so that * we can learn the length of the console log. We expect * ALOM to return the length of the entire log. We get * a snapshot of the length of the log here - it may however * continue to grow as we're reading it. We read only as * much of the log as we get in this snapshot. */ rscCmd.start_seq = 0; rscCmd.length = 0; Message.type = DP_GET_CONSOLE_LOG; Message.len = sizeof (rscCmd); Message.data = (char *)&rscCmd; ADM_Send(&Message); Timeout.tv_nsec = 0; Timeout.tv_sec = ADM_TIMEOUT; ADM_Recv(&Message, &Timeout, DP_GET_CONSOLE_LOG_R, sizeof (*rscReply)); rscReply = (dp_get_console_log_r_t *)Message.data; /* * If we do not want the whole log, and the log is bigger than * the length limit, then fetch just the last ADM_DEFAULT_LOG_LENGTH * bytes from the log. Else just get the whole thing. */ if ((all == 0) && (rscReply->remaining_log_bytes > ADM_DEFAULT_LOG_LENGTH)) { bytes_remaining = ADM_DEFAULT_LOG_LENGTH; seqno = (rscReply->remaining_log_bytes + rscReply->next_seq) - bytes_remaining; } else { bytes_remaining = rscReply->remaining_log_bytes; seqno = rscReply->next_seq; } request_size = sizeof (rscReply->buffer); ADM_Free(&Message); /* * Timeout for RSC response. */ Timeout.tv_nsec = 0; Timeout.tv_sec = ADM_TIMEOUT; /* * This loop runs as long as there is data in the log, or until * we hit the default limit (above). It's possible that ALOM may * shrink the log - we need to account for this. If ALOM returns * no data, we bail out. */ while (bytes_remaining) { rscCmd.start_seq = seqno; rscCmd.length = (bytes_remaining < request_size) ? bytes_remaining : request_size; Message.type = DP_GET_CONSOLE_LOG; Message.len = sizeof (rscCmd); Message.data = (char *)&rscCmd; ADM_Send(&Message); ADM_Recv(&Message, &Timeout, DP_GET_CONSOLE_LOG_R, sizeof (*rscReply)); rscReply = (dp_get_console_log_r_t *)Message.data; /* If ALOM returns zero bytes, we're done. */ response_size = rscReply->length; if (response_size == 0) { ADM_Free(&Message); break; } bytes_remaining -= response_size; if (rscReply->remaining_log_bytes < bytes_remaining) { bytes_remaining = rscReply->remaining_log_bytes; } /* * If the byte at the original sequence number is no * longer in the log, print a message. */ if (rscReply->next_seq > seqno + response_size) { printf(gettext("\nscadm: lost %d bytes of log data\n"), rscReply->next_seq - (seqno + response_size)); } seqno = rscReply->next_seq; /* Print the console log */ if (fwrite(rscReply->buffer, sizeof (char), response_size, stdout) != response_size) { perror(gettext("\ncouldn't write console log buffer" " to stdout")); ADM_Free(&Message); break; } ADM_Free(&Message); } putchar('\n'); }