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
ADM_Process_fru_log(int all)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