~ubuntu-branches/debian/sid/librtas/sid

« back to all changes in this revision

Viewing changes to librtasevent_src/print_rtas_event.c

  • Committer: Package Import Robot
  • Author(s): Aurelien Jarno
  • Date: 2012-06-26 23:57:57 UTC
  • Revision ID: package-import@ubuntu.com-20120626235757-rklmh5nysb9onb9v
Tags: upstream-1.3.6
ImportĀ upstreamĀ versionĀ 1.3.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @file print_rtas_event.c
 
3
 * @brief generic routines to handle printing RTAS event sections
 
4
 *
 
5
 * Copyriht (C) 2005 IBM Corporation
 
6
 * Common Public License Version 1.0 (see COPYRIGHT)
 
7
 *
 
8
 * @author Nathan Fontenot <nfont@austin.ibm.com>
 
9
 */
 
10
 
 
11
#include <stdio.h>
 
12
#include <stdlib.h>
 
13
#include <errno.h>
 
14
#include <stdarg.h>
 
15
#include <string.h>
 
16
 
 
17
#include "librtasevent.h"
 
18
#include "rtas_event.h"
 
19
 
 
20
/**
 
21
 * rtas_print_width
 
22
 * @brief character width of the librtasevent output
 
23
 *
 
24
 * The default output of librtasevent is 80 characters wide.  This can
 
25
 * be adjusted via the rtas_set_print_width() call.
 
26
 */
 
27
static int rtas_print_width = 80;
 
28
 
 
29
/**
 
30
 * line_offset
 
31
 * @brief current character offset into the print line
 
32
 */
 
33
static int line_offset = 0;
 
34
 
 
35
/**
 
36
 * ostream
 
37
 * @brief output stream for librtasevent printing
 
38
 */
 
39
static FILE *ostream;
 
40
 
 
41
/**
 
42
 * re_print_fns
 
43
 * @brief arrary of function pointers for printing RTAS event sections
 
44
 *
 
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.
 
48
 */
 
49
static int (*re_print_fns[])() = {
 
50
    NULL,
 
51
    print_re_hdr_scn,
 
52
    print_re_exthdr_scn,
 
53
    print_re_epow_scn,
 
54
    print_re_io_scn,
 
55
    print_re_cpu_scn,
 
56
    print_re_ibm_diag_scn,
 
57
    print_re_mem_scn,
 
58
    print_re_post_scn,
 
59
    print_re_ibmsp_scn,
 
60
    print_re_vend_errlog_scn,
 
61
    print_re_priv_hdr_scn,
 
62
    print_re_usr_hdr_scn,
 
63
    print_re_dump_scn,
 
64
    print_re_lri_scn,
 
65
    print_re_mt_scn,
 
66
    print_re_src_scn,
 
67
    print_re_src_scn,
 
68
    print_re_generic_scn,
 
69
};
 
70
 
 
71
/**
 
72
 * rtas_severity_names
 
73
 * @brief description of the RTAS severity levels
 
74
 */
 
75
static char *rtas_severity_names[] = {
 
76
    "No Error", "Event", "Warning", "Error Sync", "Error",
 
77
    "Fatal", "Already Reported", "(7)"
 
78
};
 
79
 
 
80
/**
 
81
 * rtas_disposition_names
 
82
 * @brief description of the RTAS event disposition levels
 
83
 */
 
84
static char *rtas_disposition_names[] = {
 
85
    "Fully Recovered", "Limited Recovery", "Not Recoverd", "(4)"
 
86
};
 
87
 
 
88
/**
 
89
 * rtas_entity_names
 
90
 * @brief description of the initiator and target names
 
91
 */
 
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)"
 
96
};
 
97
 
 
98
/**
 
99
 * rtas_error_type
 
100
 * @brief description of some of the RTAS error types
 
101
 *
 
102
 * Not all of the event types are covered in this array, please
 
103
 * bounds check before using.
 
104
 */
 
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",
 
109
};
 
110
 
 
111
/**
 
112
 * print_scn_title
 
113
 * @brief print the title of the RTAS event section
 
114
 *
 
115
 * @param fmt string format for section title
 
116
 * @param ... additional args a la printf()
 
117
 * @return number of characters printed
 
118
 */
 
119
int
 
120
print_scn_title(char *fmt, ...)
 
121
{
 
122
    va_list ap;
 
123
    int rspace;
 
124
    char buf[128];
 
125
    int i, len, offset;
 
126
 
 
127
    memset(buf, 0, sizeof(buf));
 
128
 
 
129
    offset = sprintf(buf, "==== ");
 
130
 
 
131
    va_start(ap, fmt);
 
132
    offset += vsprintf(buf + offset, fmt, ap);
 
133
    va_end(ap);
 
134
 
 
135
    offset += sprintf(buf + offset, " ");
 
136
 
 
137
    rspace = (rtas_print_width - (strlen(buf) + 2 + 9));
 
138
    for (i = 0; i < rspace; i++)
 
139
        offset += sprintf(buf + offset, "=");
 
140
 
 
141
    offset += sprintf(buf + offset, "\n");
 
142
 
 
143
    len = rtas_print(buf);
 
144
    
 
145
    return len; 
 
146
}
 
147
 
 
148
/**
 
149
 * print_raw_data
 
150
 * @brief dump raw data 
 
151
 *
 
152
 * @param data pointer to data to dump
 
153
 * @param data_len length of data to dump
 
154
 * @return number of bytes written
 
155
 */ 
 
156
int
 
157
print_raw_data(char *data, int data_len)
 
158
{
 
159
    unsigned char *h, *a;
 
160
    unsigned char *end = (unsigned char *)data + data_len;
 
161
    unsigned int offset = 0;
 
162
    int i,j;
 
163
    int len = 0;
 
164
 
 
165
    /* make sure we're starting on a new line */
 
166
    if (line_offset != 0)
 
167
        len += rtas_print("\n");
 
168
 
 
169
    h = a = (unsigned char *)data;
 
170
 
 
171
    while (h < end) {
 
172
        /* print offset */
 
173
        len += fprintf(ostream, "0x%04x:  ", offset);
 
174
        offset += 16;
 
175
 
 
176
        /* print hex */
 
177
        for (i = 0; i < 4; i++) {
 
178
            for (j = 0; j < 4; j++) {
 
179
                if (h < end)
 
180
                    len += fprintf(ostream, "%02x", *h++);
 
181
                else
 
182
                    len += fprintf(ostream, "  ");
 
183
            }
 
184
            len += fprintf(ostream, " ");
 
185
        }
 
186
 
 
187
        /* print ascii */
 
188
        len += fprintf(ostream, "    [");
 
189
        for (i = 0; i < 16; i++) {
 
190
            if (a <= end) {
 
191
                if ((*a >= ' ') && (*a <= '~'))
 
192
                    len += fprintf(ostream, "%c", *a);
 
193
                else
 
194
                    len += fprintf(ostream, ".");
 
195
                a++;
 
196
            } else
 
197
                len += fprintf(ostream, " ");
 
198
 
 
199
        }
 
200
        len += fprintf(ostream, "]\n");
 
201
    }
 
202
 
 
203
    return len;
 
204
}
 
205
 
 
206
/**
 
207
 * rtas_print_raw_event
 
208
 * @brief Dump the entire rtas event in raw format
 
209
 *
 
210
 * @param stream ouput stream to write to
 
211
 * @param re rtas_event pointer
 
212
 * @return number of bytes written
 
213
 */ 
 
214
int
 
215
rtas_print_raw_event(FILE *stream, struct rtas_event *re)
 
216
{
 
217
    int len = 0;
 
218
    
 
219
    ostream = stream;
 
220
    
 
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");
 
224
 
 
225
    return len;
 
226
}
 
227
 
 
228
/**
 
229
 * rtas_error_type
 
230
 * @brief print a description of the RTAS error type
 
231
 *
 
232
 * @param type RTAS event type
 
233
 * @return pointer to description of RTAS type
 
234
 * @return NULL on unrecognized event type
 
235
 */
 
236
static char *
 
237
rtas_error_type(int type)
 
238
{
 
239
    if (type < 11)
 
240
        return rtas_event_error_type[type];
 
241
 
 
242
    switch (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";
 
249
    }
 
250
 
 
251
    return rtas_event_error_type[0];
 
252
}
 
253
 
 
254
/**
 
255
 * rtas_set_print_width
 
256
 * @brief set the output character width for librtasevent
 
257
 *
 
258
 * @param width character width of output
 
259
 * @return 0 on success, !0 on failure
 
260
 */
 
261
int
 
262
rtas_set_print_width(int width)
 
263
{
 
264
    if ((width > 0) && (width < 1024)) {
 
265
        rtas_print_width = width;
 
266
        return 0;
 
267
    }
 
268
 
 
269
    return 1;
 
270
}
 
271
 
 
272
/** 
 
273
 * rtas_print
 
274
 * @brief routine to handle all librtas printing
 
275
 *
 
276
 * @param fmt string format a la printf()
 
277
 * @param ... additional args a la printf()
 
278
 * @return number of bytes written
 
279
 */
 
280
int
 
281
rtas_print(char *fmt, ...)
 
282
{
 
283
    va_list     ap;
 
284
    char        buf[1024];
 
285
    char        tmpbuf[1024];
 
286
    int         i;
 
287
    int         buf_offset = 0, offset = 0;
 
288
    int         tmpbuf_len;
 
289
    int         width = 0;
 
290
    int         prnt_len;
 
291
    char        *newline = NULL;
 
292
    char        *brkpt = NULL;
 
293
 
 
294
    memset(tmpbuf, 0, sizeof(tmpbuf));
 
295
    memset(buf, 0, sizeof(buf));
 
296
 
 
297
    va_start(ap, fmt);
 
298
    tmpbuf_len = vsprintf(tmpbuf, fmt, ap);
 
299
    va_end(ap);
 
300
 
 
301
    i = 0;
 
302
    while (i < tmpbuf_len) {
 
303
 
 
304
        brkpt = NULL;
 
305
        newline = NULL;
 
306
 
 
307
        for (i = offset, width = line_offset; 
 
308
             (width < rtas_print_width) && (i < tmpbuf_len); 
 
309
             i++) {
 
310
            
 
311
            switch(tmpbuf[i]) {
 
312
                case ' ':
 
313
                case '-':
 
314
                            width++;
 
315
                            brkpt = &tmpbuf[i];
 
316
                            break;
 
317
 
 
318
                case '\n':
 
319
                            newline = &tmpbuf[i];
 
320
                            width++;
 
321
                            break;
 
322
                                
 
323
                default:
 
324
                            width++;
 
325
                            break;
 
326
            }
 
327
 
 
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"); 
 
333
                offset += prnt_len;
 
334
                line_offset = 0;
 
335
                break;
 
336
            }
 
337
        }
 
338
 
 
339
        if (width >= rtas_print_width) {
 
340
 
 
341
            if (brkpt == NULL) {
 
342
               /* this won't fit on one line, break it across lines */
 
343
                prnt_len = width - line_offset + 1;
 
344
            } else {
 
345
                prnt_len = (brkpt - &tmpbuf[offset]) + 1;
 
346
            }
 
347
 
 
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");
 
352
            offset += prnt_len;
 
353
            line_offset = 0;
 
354
        }
 
355
            
 
356
    } 
 
357
 
 
358
    prnt_len = sprintf(buf + buf_offset, &tmpbuf[offset]);
 
359
    line_offset += prnt_len;
 
360
 
 
361
    return fprintf(ostream, buf);
 
362
}
 
363
 
 
364
/** 
 
365
 * rtas_print_scn
 
366
 * @brief print the contents of the specified rtas event section
 
367
 *
 
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
 
372
 */
 
373
int
 
374
rtas_print_scn(FILE *stream, struct scn_header *shdr, int verbosity)
 
375
{
 
376
    int len;
 
377
 
 
378
    if ((stream == NULL) || (shdr == NULL)) {
 
379
        errno = EFAULT;
 
380
        return 0;
 
381
    }
 
382
 
 
383
    ostream = stream;
 
384
 
 
385
    /* validate the section id */
 
386
    if (shdr->scn_id < 0) {
 
387
        errno = EFAULT;
 
388
        return 0;
 
389
    }
 
390
 
 
391
    len = re_print_fns[shdr->scn_id](shdr, verbosity);
 
392
 
 
393
    fflush(stream);
 
394
    return len;
 
395
}
 
396
 
 
397
/**
 
398
 * rtas_print_event
 
399
 * @brief print the contents of an  entire rtas event
 
400
 *
 
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
 
405
 */
 
406
int
 
407
rtas_print_event(FILE *stream, struct rtas_event *re, int verbosity)
 
408
{
 
409
    struct scn_header *shdr;
 
410
    int len = 0;
 
411
 
 
412
    if ((stream == NULL) || (re == NULL)) {
 
413
        errno = EFAULT;
 
414
        return 0;
 
415
    }
 
416
 
 
417
    ostream = stream;
 
418
 
 
419
    if (re->event_no != -1)
 
420
        len += print_scn_title("RTAS Event Dump (%d) Begin", re->event_no);
 
421
    else
 
422
        len += print_scn_title("RTAS Event Dump Begin");
 
423
 
 
424
    for (shdr = re->event_scns; shdr != NULL; shdr = shdr->next)
 
425
        len += rtas_print_scn(stream, shdr, verbosity);
 
426
 
 
427
    if (re->event_no != -1)
 
428
        len += print_scn_title("RTAS Event Dump (%d) End", re->event_no);
 
429
    else
 
430
        len += print_scn_title("RTAS Event Dump End");
 
431
 
 
432
    return len;
 
433
}
 
434
 
 
435
/**
 
436
 * rtas_get_event_hdr_scn
 
437
 * @brief Retrieve the Main RTAS event header
 
438
 *
 
439
 * @param re rtas_event pointer
 
440
 * @return pointer to rtas_event_scn for main rtas event header
 
441
 */
 
442
struct rtas_event_hdr *
 
443
rtas_get_event_hdr_scn(struct rtas_event *re)
 
444
{
 
445
    return (struct rtas_event_hdr *)get_re_scn(re, RTAS_EVENT_HDR);
 
446
}
 
447
 
 
448
/**
 
449
 * print_re_hdr_scn
 
450
 * @brief Print the contents of an RTAS main event header
 
451
 *
 
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
 
455
 */
 
456
int
 
457
print_re_hdr_scn(struct scn_header *shdr, int verbosity)
 
458
{
 
459
    struct rtas_event_hdr *re_hdr;
 
460
    int len = 0;
 
461
 
 
462
    if (shdr->scn_id != RTAS_EVENT_HDR) {
 
463
        errno = EFAULT;
 
464
        return 0;
 
465
    }    
 
466
 
 
467
    re_hdr = (struct rtas_event_hdr *)shdr;
 
468
 
 
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]);
 
472
 
 
473
    if (re_hdr->disposition || (verbosity >= 2)) {
 
474
        len += rtas_print(PRNT_FMT" (%s)\n", "Disposition:", 
 
475
                          re_hdr->disposition, 
 
476
                          rtas_disposition_names[re_hdr->disposition]);
 
477
    }
 
478
 
 
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);
 
483
    }
 
484
 
 
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]);
 
488
    }
 
489
 
 
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]);
 
493
    }
 
494
 
 
495
    len += rtas_print(PRNT_FMT" (%s)\n", "Type", re_hdr->type, 
 
496
                      rtas_error_type(re_hdr->type));
 
497
 
 
498
    return len;
 
499
}
 
500
 
 
501
/**
 
502
 * rtas_get_event_exthdr_scn
 
503
 * @brief Retrieve the RTAS Event extended header
 
504
 *
 
505
 * @param re rtas_event pointer
 
506
 * @return rtas_event_scn pointer for RTAS extended header section
 
507
 */
 
508
struct rtas_event_exthdr *
 
509
rtas_get_event_exthdr_scn(struct rtas_event *re)
 
510
{
 
511
    return (struct rtas_event_exthdr *)get_re_scn(re, RTAS_EVENT_EXT_HDR);
 
512
}
 
513
 
 
514
/**
 
515
 * print_re_exthdr_scn
 
516
 * @brief print the contents of the RTAS extended header section
 
517
 *
 
518
 * @param res rtas_event_scn pointer for the extended header
 
519
 * @param verbosity verbose level of output
 
520
 * @return number of bytes written
 
521
 */
 
522
int
 
523
print_re_exthdr_scn(struct scn_header *shdr, int verbosity)
 
524
{
 
525
    struct rtas_event_exthdr *rex_hdr;
 
526
    int len = 0;
 
527
    int version;
 
528
 
 
529
    if (shdr->scn_id != RTAS_EVENT_EXT_HDR) {
 
530
        errno = EFAULT;
 
531
        return 0;
 
532
    }    
 
533
 
 
534
    rex_hdr = (struct rtas_event_exthdr *)shdr;
 
535
    version = shdr->re->version;
 
536
 
 
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");
 
540
        else
 
541
            len += rtas_print("Extended log data can not be decoded.\n\n");
 
542
 
 
543
        return len;
 
544
    }
 
545
 
 
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" : "");
 
553
 
 
554
    if (version < 6) {
 
555
        if (version >= 3) {
 
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 "
 
563
                                  "units.\n");
 
564
        }
 
565
 
 
566
        if (rex_hdr->residual)
 
567
            len += rtas_print("Residual error from previous boot.\n");
 
568
        if (rex_hdr->boot)
 
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");
 
572
        if (rex_hdr->post)
 
573
            len += rtas_print("Error detected prior to IPL.\n");
 
574
 
 
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);
 
580
    } 
 
581
    else {
 
582
        rtas_print("\n");
 
583
    }
 
584
 
 
585
    return len;
 
586
}