Heitor Ricardo Alves de Siqueira <hal...@linux.vnet.ibm.com> writes:

> This commit implements a new iprdumpfmt command that takes an iprdump.XX file 
> as
> input and strips out driver information. This includes driver version and 
> type,
> driver trace in the correct order and SDT entries. It has a verbose option 
> that
> prints additional information for the driver trace, such as timestamps and 
> SCSI
> commands.

Hi Heitor,

We are almost there.  Applying your patch to my git tree throws the
following warnings:

[krisman@sycorax iprdd-iprutils]$ git am 
/tmp/implement-ipr-dump-formatting-tool.patch
Applying: iprutils: Implement ipr dump formatting tool
/home/krisman/work/iprdd-iprutils/.git/rebase-apply/patch:112: space before tab 
in indent.
         const char *name;
/home/krisman/work/iprdd-iprutils/.git/rebase-apply/patch:450: trailing 
whitespace.
         trace.cmd_index = raw_trace->cmd_index;
/home/krisman/work/iprdd-iprutils/.git/rebase-apply/patch:506: trailing 
whitespace.

/home/krisman/work/iprdd-iprutils/.git/rebase-apply/patch:700: trailing 
whitespace.

/home/krisman/work/iprdd-iprutils/.git/rebase-apply/patch:707: trailing 
whitespace.

warning: 5 lines add whitespace errors.

And you are also missing a sign-off tag.

That said, I ran your tool against some dumps I collected, and the
formatted output looks very good.  :)

I have one question, though. What is that '2' at the end of the Driver
Name string?  Is it expected (i.e. comes from the dump)?

[root@everest-lp10 build]# cat iprdump.write-crash.10.10.2015.report | grep 
"Driver:"
Driver: ipr2

Finally, a few comments inline.

> ---
>  Makefile.am  |   5 +-
>  iprdumpfmt.8 |  33 +++
>  iprdumpfmt.c | 650 
> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 687 insertions(+), 1 deletion(-)
>  create mode 100644 iprdumpfmt.8
>  create mode 100644 iprdumpfmt.c
>
> diff --git a/Makefile.am b/Makefile.am
> index 4636ecbaf8ce..96b0cd2a5c4c 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -10,7 +10,7 @@
>  noinst_LTLIBRARIES = libipr.la
>  libipr_la_SOURCES = iprlib.c iprlib.h
>
> -sbin_PROGRAMS = iprconfig iprdump iprupdate iprinit iprdbg
> +sbin_PROGRAMS = iprconfig iprdump iprupdate iprinit iprdbg iprdumpfmt
>  dist_sbin_SCRIPTS = iprsos
>
>  iprconfig_SOURCES = iprconfig.c iprconfig.h
> @@ -28,6 +28,9 @@ iprinit_LDADD= libipr.la
>  iprdbg_SOURCES = iprdbg.c
>  iprdbg_LDADD= libipr.la
>
> +iprdumpfmt_SOURCES = iprdumpfmt.c
> +iprdumpfmt_LDADD = libipr.la
> +
>  if STATIC_BUILD
>  sbin_PROGRAMS += iprconfig-static
>
> diff --git a/iprdumpfmt.8 b/iprdumpfmt.8
> new file mode 100644
> index 000000000000..7a3a7aea4308
> --- /dev/null
> +++ b/iprdumpfmt.8
> @@ -0,0 +1,33 @@
> +.\" (C) Copyright 2015
> +.\" International Business Machines Corporation and others.
> +.\" All Rights Reserved. This program and the accompanying
> +.\" materials are made available under the terms of the
> +.\" Common Public License v1.0 which accompanies this distribution.
> +.TH IPRDUMPFMT 8 "November 2015"
> +.SH NAME
> +iprdumpfmt \- IBM Power RAID dump formatting utility
> +.SH SYNOPSIS
> +.BI "iprdumpfmt [options] dump_file"
> +.sp
> +.BI "iprdumpfmt -o <report_file> --verbose dump_file"
> +.sp
> +.SH DESCRIPTION
> +.B iprdumpfmt
> +is used to strip out driver information from iprdump.XX files. This includes
> +driver type and version, smart dump table entries and driver trace ordered by
> +jiffies. There is a verbose option that also prints timestamps and SCSI 
> command
> +for each driver trace entry. The information is stored in a file that can be
> +optionally specified by the user. If no output file is specified, the
> +information is printed to a new 'iprdump.XX.report' file.
> +.br
> +.SH OPTIONS
> +.TP
> +.B \-\-verbose
> +Print detailed driver trace information.
> +.TP
> +.B \-\-output file
> +Specify a different output file to store formatted information. If no file is
> +chosen, a new one is created by appending '.report' to the input dump file.
> +.br
> +.SH AUTHORS
> +Heitor R. A. de Siqueira <hal...@linux.vnet.ibm.com>
> diff --git a/iprdumpfmt.c b/iprdumpfmt.c
> new file mode 100644
> index 000000000000..00e846def78e
> --- /dev/null
> +++ b/iprdumpfmt.c
> @@ -0,0 +1,650 @@

I suppose you want to add another copyright notice for this file as
well.  See iprconfig.c

> +#include <endian.h>
> +#include <getopt.h>
> +#include "iprlib.h"
> +
> +#define EYE_CATCHER_BE 0xC5D4E3F2
> +#define EYE_CATCHER_LE 0xF2E3D4C5
> +
> +#define OS_LINUX 0x4C4E5558
> +#define OS_I5OS  0x69354F53
> +
> +#define DRV_IPR2 0x49505232
> +#define DRV_V5R4 0x56355234
> +
> +#define TYPE_ASCII 0x41534349
> +#define TYPE_BIN   0x42494E41
> +#define TYPE_MR32  0x4D523332
> +#define TYPE_MR64  0x4D523634
> +
> +#define ID_IOA_DUMP     0x494F4131
> +#define ID_IOA_LOC      0x4C4F4341
> +#define ID_DRV_TRACE    0x54524143
> +#define ID_DRV_VER      0x44525652
> +#define ID_DRV_TYPE     0x54595045
> +#define ID_DRV_CTRL_BLK 0x494F4342
> +#define ID_DRV_PEND_OPS 0x414F5053
> +
> +#define IPR_DUMP_STATUS_SUCCESS      0
> +#define IPR_DUMP_STATUS_QUAL_SUCCESS 2
> +#define IPR_DUMP_STATUS_FAILED       0xFFFFFFFF
> +
> +#define IPR_FMT2_SDT_READY_TO_USE 0xC4D4E3F2
> +#define IPR_FMT3_SDT_READY_TO_USE 0xC4D4E3F3
> +
> +static const struct {
> +     const u8 op;
> +     const char *name;
> +} scsi_cmnds[] = {
> +     { 0xc1, "IPR_CANCEL_REQUEST" },
> +     { 0x01, "IPR_CANCEL_64BIT_IOARCB" },
> +     { 0xc2, "IPR_QUERY_RSRC_STATE" },
> +     { 0xc3, "IPR_RESET_DEVICE" },
> +     { 0x80, "IPR_RESET_TYPE_SELECT" },
> +     { 0x40, "IPR_LUN_RESET" },
> +     { 0x20, "IPR_TARGET_RESET" },
> +     { 0x10, "IPR_BUS_RESET" },
> +     { 0x80, "IPR_ATA_PHY_RESET" },
> +     { 0xc4, "IPR_ID_HOST_RR_Q" },
> +     { 0xc5, "IPR_QUERY_IOA_CONFIG" },
> +     { 0xce, "IPR_CANCEL_ALL_REQUESTS" },
> +     { 0xcf, "IPR_HOST_CONTROLLED_ASYNC" },
> +     { 0x01, "IPR_HCAM_CDB_OP_CODE_CONFIG_CHANGE" },
> +     { 0x02, "IPR_HCAM_CDB_OP_CODE_LOG_DATA" },
> +     { 0xfb, "IPR_SET_SUPPORTED_DEVICES" },
> +     { 0x80, "IPR_SET_ALL_SUPPORTED_DEVICES" },
> +     { 0xf7, "IPR_IOA_SHUTDOWN" },
> +     { 0x05, "IPR_WR_BUF_DOWNLOAD_AND_SAVE" },
> +
> +     { 0x00, "TEST_UNIT_READY" },
> +     { 0x01, "REZERO_UNIT" },
> +     { 0x03, "REQUEST_SENSE" },
> +     { 0x04, "FORMAT_UNIT" },
> +     { 0x05, "READ_BLOCK_LIMITS" },
> +     { 0x07, "REASSIGN_BLOCKS" },
> +     { 0x07, "INITIALIZE_ELEMENT_STATUS" },
> +     { 0x08, "READ_6" },
> +     { 0x0a, "WRITE_6" },
> +     { 0x0b, "SEEK_6" },
> +     { 0x0f, "READ_REVERSE" },
> +     { 0x10, "WRITE_FILEMARKS" },
> +     { 0x11, "SPACE" },
> +     { 0x12, "INQUIRY" },
> +     { 0x14, "RECOVER_BUFFERED_DATA" },
> +     { 0x15, "MODE_SELECT" },
> +     { 0x16, "RESERVE" },
> +     { 0x17, "RELEASE" },
> +     { 0x18, "COPY" },
> +     { 0x19, "ERASE" },
> +     { 0x1a, "MODE_SENSE" },
> +     { 0x1b, "START_STOP" },
> +     { 0x1c, "RECEIVE_DIAGNOSTIC" },
> +     { 0x1d, "SEND_DIAGNOSTIC" },
> +     { 0x1e, "ALLOW_MEDIUM_REMOVAL" },
> +     { 0x23, "READ_FORMAT_CAPACITIES" },
> +     { 0x24, "SET_WINDOW" },
> +     { 0x25, "READ_CAPACITY" },
> +     { 0x28, "READ_10" },
> +     { 0x2a, "WRITE_10" },
> +     { 0x2b, "SEEK_10" },
> +     { 0x2b, "POSITION_TO_ELEMENT" },
> +     { 0x2e, "WRITE_VERIFY" },
> +     { 0x2f, "VERIFY" },
> +     { 0x30, "SEARCH_HIGH" },
> +     { 0x31, "SEARCH_EQUAL" },
> +     { 0x32, "SEARCH_LOW" },
> +     { 0x33, "SET_LIMITS" },
> +     { 0x34, "PRE_FETCH" },
> +     { 0x34, "READ_POSITION" },
> +     { 0x35, "SYNCHRONIZE_CACHE" },
> +     { 0x36, "LOCK_UNLOCK_CACHE" },
> +     { 0x37, "READ_DEFECT_DATA" },
> +     { 0x38, "MEDIUM_SCAN" },
> +     { 0x39, "COMPARE" },
> +     { 0x3a, "COPY_VERIFY" },
> +     { 0x3b, "WRITE_BUFFER" },
> +     { 0x3c, "READ_BUFFER" },
> +     { 0x3d, "UPDATE_BLOCK" },
> +     { 0x3e, "READ_LONG" },
> +     { 0x3f, "WRITE_LONG" },
> +     { 0x40, "CHANGE_DEFINITION" },
> +     { 0x41, "WRITE_SAME" },
> +     { 0x42, "UNMAP" },
> +     { 0x43, "READ_TOC" },
> +     { 0x44, "READ_HEADER" },
> +     { 0x4a, "GET_EVENT_STATUS_NOTIFICATION" },
> +     { 0x4c, "LOG_SELECT" },
> +     { 0x4d, "LOG_SENSE" },
> +     { 0x53, "XDWRITEREAD_10" },
> +     { 0x55, "MODE_SELECT_10" },
> +     { 0x56, "RESERVE_10" },
> +     { 0x57, "RELEASE_10" },
> +     { 0x5a, "MODE_SENSE_10" },
> +     { 0x5e, "PERSISTENT_RESERVE_IN" },
> +     { 0x5f, "PERSISTENT_RESERVE_OUT" },
> +     { 0x7f, "VARIABLE_LENGTH_CMD" },
> +     { 0xa0, "REPORT_LUNS" },
> +     { 0xa2, "SECURITY_PROTOCOL_IN" },
> +     { 0xa3, "MAINTENANCE_IN" },
> +     { 0xa4, "MAINTENANCE_OUT" },
> +     { 0xa5, "MOVE_MEDIUM" },
> +     { 0xa6, "EXCHANGE_MEDIUM" },
> +     { 0xa8, "READ_12" },
> +     { 0xa9, "SERVICE_ACTION_OUT_12" },
> +     { 0xaa, "WRITE_12" },
> +     { 0xab, "SERVICE_ACTION_IN_12" },
> +     { 0xae, "WRITE_VERIFY_12" },
> +     { 0xaf, "VERIFY_12" },
> +     { 0xb0, "SEARCH_HIGH_12" },
> +     { 0xb1, "SEARCH_EQUAL_12" },
> +     { 0xb2, "SEARCH_LOW_12" },
> +     { 0xb5, "SECURITY_PROTOCOL_OUT" },
> +     { 0xb8, "READ_ELEMENT_STATUS" },
> +     { 0xb6, "SEND_VOLUME_TAG" },
> +     { 0xea, "WRITE_LONG_2" },
> +     { 0x83, "EXTENDED_COPY" },
> +     { 0x84, "RECEIVE_COPY_RESULTS" },
> +     { 0x86, "ACCESS_CONTROL_IN" },
> +     { 0x87, "ACCESS_CONTROL_OUT" },
> +     { 0x88, "READ_16" },
> +     { 0x89, "COMPARE_AND_WRITE" },
> +     { 0x8a, "WRITE_16" },
> +     { 0x8c, "READ_ATTRIBUTE" },
> +     { 0x8d, "WRITE_ATTRIBUTE" },
> +     { 0x8f, "VERIFY_16" },
> +     { 0x91, "SYNCHRONIZE_CACHE_16" },
> +     { 0x93, "WRITE_SAME_16" },
> +     { 0x9d, "SERVICE_ACTION_BIDIRECTIONAL" },
> +     { 0x9e, "SERVICE_ACTION_IN_16" },
> +     { 0x9f, "SERVICE_ACTION_OUT_16" }
> +};
> +
> +struct ipr_dump_header {
> +     u32 eye_catcher;
> +     u32 len;
> +     u32 num_entries;
> +     u32 first_entry_offset;
> +     u32 status;
> +     u32 os;
> +     u32 driver_name;
> +};
> +
> +struct ipr_dump_entry_header {
> +     u32 eye_catcher;
> +     u32 len; /* does not include entry header */
> +     u32 num_elems;
> +     u32 offset; /* offset to data from beginning of dump file */
> +     u32 data_type;
> +     u32 id;
> +     u32 status;
> +};
> +
> +struct ipr_trace_entry {
> +     u32 time;
> +
> +     u8 op_code; /* SCSI opcode */
> +     u8 ata_op_code;
> +     u8 type;
> +#define IPR_TRACE_START                      0x00
> +#define IPR_TRACE_FINISH             0xff
> +     u8 cmd_index;
> +
> +     u32 res_handle; /* stored as BE */
> +     union {
> +             u32 ioasc;
> +             u32 add_data;
> +             u32 res_addr;
> +     } u;
> +};
> +
> +struct ipr_sdt_header {
> +     /* all values in ipr_sdt_header are stored as BE */
> +     u32 state;
> +     u32 num_entries;
> +     u32 entries_used;
> +     u32 dump_size;
> +};
> +
> +static void *dump_map;    /* ipr dump memory map */
> +static FILE *out_fp;      /* output report file pointer */
> +static int verbose_trace; /* flag for verbose trace printing */
> +
> +#define TARGET_TO_HOST32(value, eye_catcher) \
> +     (eye_catcher == EYE_CATCHER_BE ? \
> +      be32toh(value) : \
> +      le32toh(value))
> +
> +/**
> + * get_scsi_command_literal -
> + * @value:           SCSI opcode
> + *
> + * Returns:
> + *   SCSI command string
> + **/
> +static const char* get_scsi_command_literal(u32 value)
> +{
> +     u32 i = 0;
> +
> +     for (i = 0; i < ARRAY_SIZE(scsi_cmnds); ++i) {
> +             if (value == scsi_cmnds[i].op)
> +                     return scsi_cmnds[i].name;
> +     }
> +     return "NULL";
> +}

Heh.  I was talking about returning NULL here as in NULL pointer (0x0).
Then it's up to the caller to handle this condition.

> +
> +/**
> + * read_dump_header -
> + * @hdr:             ipr dump header pointer
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void read_dump_header(struct ipr_dump_header *hdr)
> +{
> +     struct ipr_dump_header *raw_hdr = dump_map;
> +
> +     hdr->eye_catcher = htobe32(raw_hdr->eye_catcher);
> +
> +     /* convert to correct endianness */
> +     hdr->len = TARGET_TO_HOST32(raw_hdr->len, hdr->eye_catcher);
> +     hdr->num_entries = TARGET_TO_HOST32(raw_hdr->num_entries,
> +                                         hdr->eye_catcher);
> +     hdr->first_entry_offset = TARGET_TO_HOST32(raw_hdr->first_entry_offset,
> +                                                hdr->eye_catcher);
> +     hdr->status = TARGET_TO_HOST32(raw_hdr->status, hdr->eye_catcher);
> +     hdr->os = TARGET_TO_HOST32(raw_hdr->os, hdr->eye_catcher);
> +     hdr->driver_name = TARGET_TO_HOST32(raw_hdr->driver_name,
> +                                         hdr->eye_catcher);
> +}
> +
> +/**
> + * print_dump_header -
> + * @hdr:             ipr dump header pointer
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void print_dump_header(struct ipr_dump_header *hdr)
> +{
> +     fprintf(out_fp, "IPR Adapter Dump Report\n\n");
> +     switch (hdr->eye_catcher) {
> +     case EYE_CATCHER_BE:
> +             fprintf(out_fp, "Big Endian format: ");
> +             break;
> +     case EYE_CATCHER_LE:
> +             fprintf(out_fp, "Little Endian format: ");
> +             break;
> +     default:
> +             fprintf(out_fp, "Unknown dump format: ");
> +     }
> +     fprintf(out_fp, "Eye Catcher is 0x%08X\n", hdr->eye_catcher);
> +
> +     fprintf(out_fp, "Total length: %d bytes\n", hdr->len);
> +     fprintf(out_fp, "Number of dump entries: %d\n", hdr->num_entries);
> +     fprintf(out_fp, "Offset to first entry: 0x%08X bytes\n",
> +             hdr->first_entry_offset);
> +     fprintf(out_fp, "Dump status: 0x%08X ", hdr->status);
> +     switch (hdr->status) {
> +     case IPR_DUMP_STATUS_SUCCESS:
> +             fprintf(out_fp, "(SUCCESS)\n");
> +             break;
> +     case IPR_DUMP_STATUS_QUAL_SUCCESS:
> +             fprintf(out_fp, "(QUAL_SUCCESS)\n");
> +             break;
> +     case IPR_DUMP_STATUS_FAILED:
> +             fprintf(out_fp, "(FAILED)\n");
> +             break;
> +     default:
> +             fprintf(out_fp, "(UNKNOWN)\n");
> +     }
> +
> +     fprintf(out_fp, "Operating System: ");
> +     switch (hdr->os) {
> +     case OS_LINUX:
> +             fprintf(out_fp, "Linux\n");
> +             break;
> +     case OS_I5OS:
> +             fprintf(out_fp, "i5OS\n");
> +             break;
> +     default:
> +             fprintf(out_fp, "unknown\n");
> +     }
> +
> +     fprintf(out_fp, "Driver: ");
> +     switch (hdr->driver_name) {
> +     case DRV_IPR2:
> +             fprintf(out_fp, "ipr2\n");
> +             break;
> +     case DRV_V5R4:
> +             fprintf(out_fp, "V5R4\n");
> +             break;
> +     default:
> +             fprintf(out_fp, "unknown\n");
> +     }
> +}
> +
> +/**
> + * read_entry_header -
> + * @hdr:             ipr dump entry header pointer
> + * @offset:          offset to entry data
> + *
> + * Returns:
> + *   offset to next entry header
> + **/
> +static u32 read_entry_header(struct ipr_dump_entry_header *hdr, u32 offset)
> +{
> +     struct ipr_dump_entry_header *raw_hdr = dump_map+offset;
> +     hdr->eye_catcher = htobe32(raw_hdr->eye_catcher);
> +
> +     /* convert to correct endianness */
> +     hdr->len = TARGET_TO_HOST32(raw_hdr->len, hdr->eye_catcher);
> +     hdr->num_elems = TARGET_TO_HOST32(raw_hdr->num_elems, hdr->eye_catcher);
> +     hdr->offset = TARGET_TO_HOST32(raw_hdr->offset, hdr->eye_catcher);
> +     hdr->data_type = TARGET_TO_HOST32(raw_hdr->data_type, hdr->eye_catcher);
> +     hdr->id = TARGET_TO_HOST32(raw_hdr->id, hdr->eye_catcher);
> +     hdr->status = TARGET_TO_HOST32(raw_hdr->status, hdr->eye_catcher);
> +     hdr->offset += offset;
> +
> +     return (hdr->offset + hdr->len);
> +}
> +
> +/**
> + * read_trace_data -
> + * @offset:          offset to entry data
> + * @eye_catcher:     ipr entry eye catcher
> + *
> + * Returns:
> + *   ipr trace entry structure
> + **/
> +static struct ipr_trace_entry read_trace_data(u32 offset, u32 eye_catcher)
> +{
> +     struct ipr_trace_entry trace;
> +     struct ipr_trace_entry *raw_trace = dump_map+offset;
> +
> +        /* always stored as BE */
> +     trace.res_handle = htobe32(raw_trace->res_handle);
> +
> +     /* convert to correct endianness */
> +     trace.time = TARGET_TO_HOST32(raw_trace->time, eye_catcher);
> +     trace.u.add_data = TARGET_TO_HOST32(raw_trace->u.add_data, eye_catcher);
> +
> +     /* copy remaining trace fields */
> +     trace.op_code = raw_trace->op_code;
> +     trace.ata_op_code = raw_trace->ata_op_code;
> +     trace.type = raw_trace->type;
> +     trace.cmd_index = raw_trace->cmd_index; 
> +
> +     return trace;
> +}
> +
> +#define JIFF_TO_USEC(x) x * 1000 * 1000 / sysconf(_SC_CLK_TCK)
> +/**
> + * print_trace -
> + * @hdr:             ipr entry header pointer
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void print_trace(struct ipr_dump_entry_header *hdr)
> +{
> +     u32 i, min_pos, min_time, num_entries, offset;
> +     struct ipr_trace_entry *raw_trace;
> +     struct ipr_trace_entry t;
> +
> +     num_entries = hdr->len / sizeof(*raw_trace);
> +     raw_trace = dump_map + hdr->offset;
> +     min_pos = 0;
> +     min_time = TARGET_TO_HOST32(raw_trace->time, hdr->eye_catcher);
> +
> +     fprintf(out_fp, "\t entries found: %d\n\n", num_entries);
> +     for (i = 1; i < num_entries; ++i) {
> +             raw_trace = dump_map + hdr->offset + i*sizeof(*raw_trace);
> +             if (TARGET_TO_HOST32(raw_trace->time, hdr->eye_catcher) <
> +                 min_time) {
> +                     min_time = TARGET_TO_HOST32(raw_trace->time,
> +                                                 hdr->eye_catcher);
> +                     min_pos = i;
> +             }
> +     }
> +     for (i = 0; i < num_entries; ++i) {
> +             offset = hdr->offset +
> +                     ((min_pos+i)%num_entries) * sizeof(*raw_trace);
> +             t = read_trace_data(offset, hdr->eye_catcher);
> +             fprintf(out_fp, "\t %08X %02X%02X%02X%02X %08X %08X",
> +                     t.time, t.op_code, t.ata_op_code, t.type, t.cmd_index,
> +                     t.res_handle, t.u.add_data);
> +             if (verbose_trace) {
> +                     fprintf(out_fp, "\t | \t%lld\xC2\xB5s\t",
> +                             (long long unsigned)JIFF_TO_USEC(t.time));
> +                     switch(t.type) {
> +                     case IPR_TRACE_START:
> +                             fprintf(out_fp, "IPR_TRACE_START\t\t");
> +                             break;
> +                     case IPR_TRACE_FINISH:
> +                             fprintf(out_fp, "IPR_TRACE_FINISH\t");
> +                             break;
> +                     default:
> +                             fprintf(out_fp, "\t\t\t");
> +                     }
> +                     fprintf(out_fp, "%s",
> +                             get_scsi_command_literal(t.op_code));
> +                     
> +             }
> +             fprintf(out_fp, "\n");
> +     }
> +}
> +
> +/**
> + * print_sdt -
> + * @data_offset:     offset to sdt data
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void print_sdt(u32 data_offset)
> +{
> +     u32 i;
> +     struct ipr_sdt_header *raw_hdr;
> +     struct ipr_sdt_entry *raw_entry;
> +
> +     raw_hdr = dump_map + data_offset;
> +
> +     fprintf(out_fp, "\t state: 0x%X", htobe32(raw_hdr->state));
> +     if (htobe32(raw_hdr->state) == IPR_FMT2_SDT_READY_TO_USE ||
> +         htobe32(raw_hdr->state) == IPR_FMT3_SDT_READY_TO_USE)
> +             fprintf(out_fp, " (READY_TO_USE)\n");
> +     else
> +             fprintf(out_fp, "\n");
> +     fprintf(out_fp, "\t entries found: %d\n\n",
> +             htobe32(raw_hdr->entries_used));
> +
> +     for (i = 0; i < htobe32(raw_hdr->entries_used); ++i) {
> +             raw_entry = dump_map + data_offset + sizeof(*raw_hdr)
> +                     + i * sizeof(*raw_entry);
> +             fprintf(out_fp, "\t %08X %08X %02X%02X%02X%02X %04X\n",
> +                     htobe32(raw_entry->bar_str_offset),
> +                     htobe32(raw_entry->end_offset),
> +                     raw_entry->entry_byte, raw_entry->endian,
> +                     raw_entry->valid_entry, raw_entry->resv,
> +                     htobe16(raw_entry->priority));
> +     }
> +}
> +
> +/**
> + * dump_entry_data -
> + * @hdr:             ipr dump entry header pointer
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void dump_entry_data(struct ipr_dump_entry_header *hdr)
> +{
> +     u32 i;
> +     char *s;
> +
> +     switch (hdr->id) {
> +     case ID_IOA_DUMP:
> +             fprintf(out_fp, "Smart Dump Table Data:\n");
> +             print_sdt(hdr->offset);
> +             break;
> +     case ID_IOA_LOC:
> +             fprintf(out_fp, "IOA Location:\n");
> +             s = dump_map+hdr->offset;
> +             fprintf(out_fp, "\t %.*s\n\n", hdr->len, s);
> +             break;
> +     case ID_DRV_VER:
> +             fprintf(out_fp, "Driver Version:\n");
> +             s = dump_map+hdr->offset;
> +             fprintf(out_fp, "\t %.*s\n\n", hdr->len, s);
> +             break;
> +     case ID_DRV_TRACE:
> +             fprintf(out_fp, "Driver Trace Entries:\n");
> +             print_trace(hdr);
> +             fprintf(out_fp, "\n");
> +             break;
> +     case ID_DRV_TYPE:
> +             fprintf(out_fp, "Driver Type:\n");
> +             i = TARGET_TO_HOST32(*(int*)(dump_map+hdr->offset),
> +                                  hdr->eye_catcher);
> +             fprintf(out_fp, "\t CCIN: 0x%04X\n", i);
> +             i = TARGET_TO_HOST32(*(int*)(dump_map+hdr->offset+sizeof(i)),
> +                                  hdr->eye_catcher);
> +             fprintf(out_fp,"\t Adapter firmware Version: "
> +                     " %02X:%02X:%02X:%02X\n\n",
> +                     i >> 24,                /* major release */
> +                     (i & 0x00FF0000) >> 16, /* card type */
> +                     (i & 0x0000FF00) >> 8,  /* minor release 0 */
> +                     i & 0x000000FF);        /* minor release 1 */
> +             break;
> +     case ID_DRV_CTRL_BLK:
> +     case ID_DRV_PEND_OPS:
> +             /* not implemented yet */
> +             fprintf(stderr,
> +                     "Warning: found IPR Control Block or IPR Pending Ops!\n"
> +                     "These are not implemented yet. Skipping...\n");
> +             break;
> +     default:
> +             fprintf(stderr,
> +                     "Warning: did not recognize data identification "
> +                     "(id 0x%08X). Skipping...\n\n", hdr->id);
> +     }
> +}
> +
> +/**
> + * fsize -
> + * @filename:                ipr dump file name
> + *
> + * Returns:
> + *   ipr dump file size
> + **/
> +off_t fsize(const char *filename)
> +{
> +     struct stat st;
> +
> +     if (stat(filename, &st) == 0)
> +             return st.st_size;
> +
> +     return -1;
> +}
> +
> +/**
> + * print_usage -
> + *
> + * Returns:
> + *   nothing
> + **/
> +static void print_usage()
> +{
> +     fprintf(stdout,
> +             "Usage: iprdumpfmt [options] dump_file\n"
> +             "  Options:\n"
> +             "\t-h --help\tPrint this message\n"
> +             "\t-o --output\tSpecify an output file\n"
> +             "\t-v --verbose\tPrint verbose trace data\n");
> +}
> +
> +static struct option long_options[] = {
> +     {"output", required_argument, 0, 'o'},
> +     {"help", no_argument, 0, 'h'},
> +     {"verbose", no_argument, &verbose_trace, 1},
> +     {0, 0, 0, 0}
> +};
> +
> +int main(int argc, char *argv[])
> +{
> +     u32 i, offset;
> +     int in_fd, filesize;
> +     struct ipr_dump_header hdr;
> +     struct ipr_dump_entry_header entry_hdr;
> +     int c, option_index = 0;
> +     char out_filename[1000] = {'\0'};
> +
> +     while ((c = getopt_long(argc, argv, "hvo:", long_options,
> +                             &option_index)) != -1) {
> +             switch (c) {
> +             case 0:
> +                     break;
> +             case 'o':
> +                     strncpy(out_filename, optarg, sizeof(out_filename) - 1);
> +                     break;
> +             case '?':
> +             case 'h':
> +                     print_usage();
> +                     return 0;
> +             case 'v':
> +                     verbose_trace = 1;
> +                     break;
> +             default:
> +                     return -1;
> +             }
> +     }
> +
> +     if (argc - optind < 1) {
> +             /* needs at least a dump file */
> +             print_usage();
> +             return -1;
> +     }
> +
> +     in_fd = open(argv[optind], O_RDONLY);
> +     if (in_fd < 0) {
> +             fprintf(stderr, "Could not open dump file %s: %s\n",
> +                     argv[optind], strerror(errno));
> +             return errno;
> +     }
> +
> +     if (out_filename[0] == '\0') {
> +             strncat(out_filename, argv[optind], sizeof(out_filename) - 1);
> +             strncat(out_filename, ".report", sizeof(out_filename) - 1);
> +     }

Instead of strncat, you can use a single function:

snprintf(out_filename, size, "%s.report", argv[optind]);

> +     out_fp = fopen(out_filename, "w");
> +     if (out_fp == NULL) {
> +             fprintf(stderr, "Could not open output file %s: %s\n",
> +                     out_filename, strerror(errno));
> +             return errno;

The fprintf call will overwrite errno, causing you to return a wrong
error code (See the Notes section in errno(3)).  You must either save
errno to a ret variable beforehand, or just return some constant error
value.

> +     }
> +     
> +     filesize = fsize(argv[optind]);
> +     if (filesize < 0) {
> +             fprintf(stderr, "Could not determine size of %s: %s\n",
> +                     argv[optind], strerror(errno));
> +             return errno;
> +     }
> +     
> +     dump_map = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, in_fd, 0);
> +     if (dump_map == MAP_FAILED) {
> +             fprintf(stderr, "Could not map dump file to memory: %s\n",
> +                     strerror(errno));
> +             return errno;
> +     }
> +
> +     read_dump_header(&hdr);
> +     print_dump_header(&hdr);
> +     fprintf(out_fp, "\n");
> +
> +     offset = hdr.first_entry_offset;
> +     for (i = 0; i < hdr.num_entries; ++i) {
> +             offset = read_entry_header(&entry_hdr, offset);
> +             dump_entry_data(&entry_hdr);
> +     }
> +
> +     return 0;
> +}

Thanks,

-- 
Gabriel Krisman Bertazi


------------------------------------------------------------------------------
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to