2
* @file print_rtas_event.c
3
* @brief generic routines to handle printing RTAS event sections
5
* Copyriht (C) 2005 IBM Corporation
6
* Common Public License Version 1.0 (see COPYRIGHT)
8
* @author Nathan Fontenot <nfont@austin.ibm.com>
17
#include "librtasevent.h"
18
#include "rtas_event.h"
22
* @brief character width of the librtasevent output
24
* The default output of librtasevent is 80 characters wide. This can
25
* be adjusted via the rtas_set_print_width() call.
27
static int rtas_print_width = 80;
31
* @brief current character offset into the print line
33
static int line_offset = 0;
37
* @brief output stream for librtasevent printing
43
* @brief arrary of function pointers for printing RTAS event sections
45
* NOTE: the index of these print functions corresponds to the
46
* definitions for the rtas event sections from librtasevent.h. Changes
47
* need to be made in both places to avoid breaking librtasevent.
49
static int (*re_print_fns[])() = {
56
print_re_ibm_diag_scn,
60
print_re_vend_errlog_scn,
61
print_re_priv_hdr_scn,
73
* @brief description of the RTAS severity levels
75
static char *rtas_severity_names[] = {
76
"No Error", "Event", "Warning", "Error Sync", "Error",
77
"Fatal", "Already Reported", "(7)"
81
* rtas_disposition_names
82
* @brief description of the RTAS event disposition levels
84
static char *rtas_disposition_names[] = {
85
"Fully Recovered", "Limited Recovery", "Not Recoverd", "(4)"
90
* @brief description of the initiator and target names
92
char *rtas_entity_names[] = { /* for initiator & targets */
93
"Unknown", "CPU", "PCI", "ISA", "Memory", "Power Management",
94
"Hot Plug", "(7)", "(8)", "(9)", "(10)", "(11)", "(12)",
95
"(13)", "(14)", "(15)"
100
* @brief description of some of the RTAS error types
102
* Not all of the event types are covered in this array, please
103
* bounds check before using.
105
static char *rtas_event_error_type[] = {
106
"Unknown", "Retry", "TCE Error", "Internal Device Failure",
107
"Timeout", "Data Parity", "Address Parity", "Cache Parity",
108
"Address Invalid", "ECC Uncorrected", "ECC Corrupted",
113
* @brief print the title of the RTAS event section
115
* @param fmt string format for section title
116
* @param ... additional args a la printf()
117
* @return number of characters printed
120
print_scn_title(char *fmt, ...)
127
memset(buf, 0, sizeof(buf));
129
offset = sprintf(buf, "==== ");
132
offset += vsprintf(buf + offset, fmt, ap);
135
offset += sprintf(buf + offset, " ");
137
rspace = (rtas_print_width - (strlen(buf) + 2 + 9));
138
for (i = 0; i < rspace; i++)
139
offset += sprintf(buf + offset, "=");
141
offset += sprintf(buf + offset, "\n");
143
len = rtas_print(buf);
150
* @brief dump raw data
152
* @param data pointer to data to dump
153
* @param data_len length of data to dump
154
* @return number of bytes written
157
print_raw_data(char *data, int data_len)
159
unsigned char *h, *a;
160
unsigned char *end = (unsigned char *)data + data_len;
161
unsigned int offset = 0;
165
/* make sure we're starting on a new line */
166
if (line_offset != 0)
167
len += rtas_print("\n");
169
h = a = (unsigned char *)data;
173
len += fprintf(ostream, "0x%04x: ", offset);
177
for (i = 0; i < 4; i++) {
178
for (j = 0; j < 4; j++) {
180
len += fprintf(ostream, "%02x", *h++);
182
len += fprintf(ostream, " ");
184
len += fprintf(ostream, " ");
188
len += fprintf(ostream, " [");
189
for (i = 0; i < 16; i++) {
191
if ((*a >= ' ') && (*a <= '~'))
192
len += fprintf(ostream, "%c", *a);
194
len += fprintf(ostream, ".");
197
len += fprintf(ostream, " ");
200
len += fprintf(ostream, "]\n");
207
* rtas_print_raw_event
208
* @brief Dump the entire rtas event in raw format
210
* @param stream ouput stream to write to
211
* @param re rtas_event pointer
212
* @return number of bytes written
215
rtas_print_raw_event(FILE *stream, struct rtas_event *re)
221
len += print_scn_title("Raw RTAS Event Begin");
222
len += print_raw_data(re->buffer, re->event_length);
223
len += print_scn_title("Raw RTAS Event End");
230
* @brief print a description of the RTAS error type
232
* @param type RTAS event type
233
* @return pointer to description of RTAS type
234
* @return NULL on unrecognized event type
237
rtas_error_type(int type)
240
return rtas_event_error_type[type];
243
case 64: return "EPOW";
244
case 224: return "Platform Error";
245
case 225: return "I/O Event";
246
case 226: return "Platform Information Event";
247
case 227: return "Resource Deallocation Event";
248
case 228: return "Dump Notification Event";
251
return rtas_event_error_type[0];
255
* rtas_set_print_width
256
* @brief set the output character width for librtasevent
258
* @param width character width of output
259
* @return 0 on success, !0 on failure
262
rtas_set_print_width(int width)
264
if ((width > 0) && (width < 1024)) {
265
rtas_print_width = width;
274
* @brief routine to handle all librtas printing
276
* @param fmt string format a la printf()
277
* @param ... additional args a la printf()
278
* @return number of bytes written
281
rtas_print(char *fmt, ...)
287
int buf_offset = 0, offset = 0;
291
char *newline = NULL;
294
memset(tmpbuf, 0, sizeof(tmpbuf));
295
memset(buf, 0, sizeof(buf));
298
tmpbuf_len = vsprintf(tmpbuf, fmt, ap);
302
while (i < tmpbuf_len) {
307
for (i = offset, width = line_offset;
308
(width < rtas_print_width) && (i < tmpbuf_len);
319
newline = &tmpbuf[i];
328
if (newline != NULL) {
329
prnt_len = newline - &tmpbuf[offset] + 1;
330
snprintf(buf + buf_offset, prnt_len, &tmpbuf[offset]);
331
buf_offset = strlen(buf);
332
buf_offset += sprintf(buf + buf_offset, "\n");
339
if (width >= rtas_print_width) {
342
/* this won't fit on one line, break it across lines */
343
prnt_len = width - line_offset + 1;
345
prnt_len = (brkpt - &tmpbuf[offset]) + 1;
348
/* print up to the last brkpt */
349
snprintf(buf + buf_offset, prnt_len, &tmpbuf[offset]);
350
buf_offset = strlen(buf);
351
buf_offset += sprintf(buf + buf_offset, "\n");
358
prnt_len = sprintf(buf + buf_offset, &tmpbuf[offset]);
359
line_offset += prnt_len;
361
return fprintf(ostream, buf);
366
* @brief print the contents of the specified rtas event section
368
* @param stream output stream to write to
369
* @param res rtas_event_scn pointer to print
370
* @param verbosity verbose level for output
371
* @return number of bytes written
374
rtas_print_scn(FILE *stream, struct scn_header *shdr, int verbosity)
378
if ((stream == NULL) || (shdr == NULL)) {
385
/* validate the section id */
386
if (shdr->scn_id < 0) {
391
len = re_print_fns[shdr->scn_id](shdr, verbosity);
399
* @brief print the contents of an entire rtas event
401
* @param stream output stream to print to
402
* @param re rtas_event pointer to print out
403
* @param verbosity verbose level of output
404
* @return number of bytes written
407
rtas_print_event(FILE *stream, struct rtas_event *re, int verbosity)
409
struct scn_header *shdr;
412
if ((stream == NULL) || (re == NULL)) {
419
if (re->event_no != -1)
420
len += print_scn_title("RTAS Event Dump (%d) Begin", re->event_no);
422
len += print_scn_title("RTAS Event Dump Begin");
424
for (shdr = re->event_scns; shdr != NULL; shdr = shdr->next)
425
len += rtas_print_scn(stream, shdr, verbosity);
427
if (re->event_no != -1)
428
len += print_scn_title("RTAS Event Dump (%d) End", re->event_no);
430
len += print_scn_title("RTAS Event Dump End");
436
* rtas_get_event_hdr_scn
437
* @brief Retrieve the Main RTAS event header
439
* @param re rtas_event pointer
440
* @return pointer to rtas_event_scn for main rtas event header
442
struct rtas_event_hdr *
443
rtas_get_event_hdr_scn(struct rtas_event *re)
445
return (struct rtas_event_hdr *)get_re_scn(re, RTAS_EVENT_HDR);
450
* @brief Print the contents of an RTAS main event header
452
* @param res rtas_event_scn pointer for main RTAS event header
453
* @param verbosity verbose level for output
454
* @return number of bytes written
457
print_re_hdr_scn(struct scn_header *shdr, int verbosity)
459
struct rtas_event_hdr *re_hdr;
462
if (shdr->scn_id != RTAS_EVENT_HDR) {
467
re_hdr = (struct rtas_event_hdr *)shdr;
469
len += rtas_print(PRNT_FMT" ", "Version:", re_hdr->version);
470
len += rtas_print(PRNT_FMT" (%s)\n", "Severity:", re_hdr->severity,
471
rtas_severity_names[re_hdr->severity]);
473
if (re_hdr->disposition || (verbosity >= 2)) {
474
len += rtas_print(PRNT_FMT" (%s)\n", "Disposition:",
476
rtas_disposition_names[re_hdr->disposition]);
479
if (verbosity >= 2) {
480
len += rtas_print(PRNT_FMT" ", "Extended:", re_hdr->extended);
481
len += rtas_print(PRNT_FMT"\n", "Log Length:",
482
re_hdr->ext_log_length);
485
if (re_hdr->initiator || verbosity >=2) {
486
len += rtas_print(PRNT_FMT" (%s)\n", "Initiator", re_hdr->initiator,
487
rtas_entity_names[re_hdr->initiator]);
490
if (re_hdr->target || (verbosity >= 2)) {
491
len += rtas_print(PRNT_FMT" (%s)\n", "Target", re_hdr->target,
492
rtas_entity_names[re_hdr->target]);
495
len += rtas_print(PRNT_FMT" (%s)\n", "Type", re_hdr->type,
496
rtas_error_type(re_hdr->type));
502
* rtas_get_event_exthdr_scn
503
* @brief Retrieve the RTAS Event extended header
505
* @param re rtas_event pointer
506
* @return rtas_event_scn pointer for RTAS extended header section
508
struct rtas_event_exthdr *
509
rtas_get_event_exthdr_scn(struct rtas_event *re)
511
return (struct rtas_event_exthdr *)get_re_scn(re, RTAS_EVENT_EXT_HDR);
515
* print_re_exthdr_scn
516
* @brief print the contents of the RTAS extended header section
518
* @param res rtas_event_scn pointer for the extended header
519
* @param verbosity verbose level of output
520
* @return number of bytes written
523
print_re_exthdr_scn(struct scn_header *shdr, int verbosity)
525
struct rtas_event_exthdr *rex_hdr;
529
if (shdr->scn_id != RTAS_EVENT_EXT_HDR) {
534
rex_hdr = (struct rtas_event_exthdr *)shdr;
535
version = shdr->re->version;
537
if (!rex_hdr->valid) {
538
if (rex_hdr->bigendian && rex_hdr->power_pc)
539
len += rtas_print("Extended log data is not valid.\n\n");
541
len += rtas_print("Extended log data can not be decoded.\n\n");
546
/* Dump useful stuff in the rex_hdr */
547
len += rtas_print("%-19s%s%s%s%s%s\n", "Status:",
548
rex_hdr->unrecoverable ? " unrecoverable" : "",
549
rex_hdr->recoverable ? " recoverable" : "",
550
rex_hdr->unrecoverable_bypassed ? " bypassed" : "",
551
rex_hdr->predictive ? " predictive" : "",
552
rex_hdr->newlog ? " new" : "");
556
if (rex_hdr->non_hardware)
557
len += rtas_print("Error may be caused by defects in "
558
"software or firmware.\n");
559
if (rex_hdr->hot_plug)
560
len += rtas_print("Error is isolated to hot-pluggable unit.\n");
561
if (rex_hdr->group_failure)
562
len += rtas_print("Error is isolated to a group of failing "
566
if (rex_hdr->residual)
567
len += rtas_print("Residual error from previous boot.\n");
569
len += rtas_print("Error detected during IPL process.\n");
570
if (rex_hdr->config_change)
571
len += rtas_print("Configuration changed since last boot.\n");
573
len += rtas_print("Error detected prior to IPL.\n");
575
len += rtas_print("%-20s%x/%x/%x %-20s%x:%x:%x:%x\n\n", "Date:",
576
rex_hdr->date.year, rex_hdr->date.month,
577
rex_hdr->date.day, "Time:", rex_hdr->time.hour,
578
rex_hdr->time.minutes, rex_hdr->time.seconds,
579
rex_hdr->time.hundredths);