1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
/*
* 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.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* consolelog.c: support for the scadm consolelog option (to display the
* service processor console log)
*/
#include <libintl.h>
#include <stdio.h>
#include <string.h>
#include <time.h> /* required by librsc.h */
#include <limits.h>
#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');
}
|