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 * config.c: support for the scadm configlog option (to display the
31 * service processor configuration 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
ADM_Process_fru_log(int all)46 ADM_Process_fru_log(int all)
47 {
48 rscp_msg_t Message;
49 struct timespec Timeout;
50 dp_get_config_log_r_t *rscReply;
51 rsci64 bytes_remaining, seqno;
52 rsci16 request_size, response_size;
53 dp_get_config_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_CONFIG_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_CONFIG_LOG_R, sizeof (*rscReply));
76
77 rscReply = (dp_get_config_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_CONFIG_LOG;
113 Message.len = sizeof (rscCmd);
114 Message.data = (char *)&rscCmd;
115 ADM_Send(&Message);
116
117 ADM_Recv(&Message, &Timeout,
118 DP_GET_CONFIG_LOG_R, sizeof (*rscReply));
119
120 rscReply = (dp_get_config_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 config log */
144 if (fwrite(rscReply->buffer, sizeof (char), response_size,
145 stdout) != response_size) {
146 perror(gettext("\ncouldn't write config log buffer"
147 " to stdout"));
148 ADM_Free(&Message);
149 break;
150 }
151 ADM_Free(&Message);
152 }
153 putchar('\n');
154 }
155