commit ac0a91d2730740cd279d80ccd4c83b0a04827d1d
Author: Nathan Fontenot <nfont@linux.vnet.ibm.com>
Date:   Fri Oct 17 10:10:29 2014 -0400

    LE Support for SRC/FRU events
    
    Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com>

diff --git a/librtasevent_src/librtasevent_v6.h b/librtasevent_src/librtasevent_v6.h
index 7fdcb17..7097bb0 100644
--- a/librtasevent_src/librtasevent_v6.h
+++ b/librtasevent_src/librtasevent_v6.h
@@ -267,9 +267,15 @@ struct rtas_lri_scn_raw {
 struct rtas_fru_hdr {
     struct rtas_fru_hdr *next;
     char        id[2];
+    uint32_t    length;
+    uint32_t    flags;
+};
+
+struct rtas_fru_hdr_raw {
+    char        id[2];
     uint32_t    length:8;
     uint32_t    flags:8;
-};
+}__attribute__((__packed__));
 
 #define RE_FRU_HDR_SZ           4
 #define RE_FRU_HDR_OFFSET(x)    ((char *)(x) + sizeof(struct rtas_fru_hdr *))
@@ -307,6 +313,16 @@ struct rtas_fru_id_scn {
     char serial_no[13];
 };
 
+struct rtas_fru_id_scn_raw {
+    struct rtas_fru_hdr_raw fruhdr;
+
+    /* The following fields may not be present */
+    char part_no[8];
+    char procedure_id[8];
+    char ccin[5];
+    char serial_no[13];
+}__attribute__((__packed__));
+
 /**
  * @struct rtas_fru_pe_scn
  * @brief contents of the FRU Power Enclosure Substructure
@@ -317,11 +333,22 @@ struct rtas_fru_pe_scn {
     char pce_name[32];
 };
 
+struct rtas_fru_pe_scn_raw {
+    struct rtas_fru_hdr_raw fruhdr;
+    struct rtas_mtms pce_mtms;
+    char pce_name[32];
+}__attribute__((__packed__));
+
 /**
  * @struct fru_mru
  * @brief FRU MR Description structs
  */
 struct fru_mru {
+    char        priority;
+    uint32_t    id;
+};
+
+struct fru_mru_raw {
     uint32_t    /* reserved */:24;
     char        priority;
     uint32_t    id;
@@ -339,18 +366,24 @@ struct rtas_fru_mr_scn {
     uint32_t    /* reserved */:32;
     struct fru_mru  mrus[15];
 };
+
+struct rtas_fru_mr_scn_raw {
+    struct rtas_fru_hdr_raw fruhdr;
+    uint32_t    /* reserved */:32;
+    struct fru_mru_raw  mrus[15];
+};
     
 /**
  * @struct rtas_v6_fru_scn
  * @brief RTAS version 6 FRU callout section
  */
 struct rtas_fru_scn {
-    uint32_t    length:8;               /**< call-out length */
-    uint32_t    type:4;                 /**< callout type */
-    uint32_t    fru_id_included:1;      /**< fru id subsection included */
-    uint32_t    fru_subscn_included:3;
+    uint32_t    length;               /**< call-out length */
+    uint32_t    type;                 /**< callout type */
+    uint32_t    fru_id_included;      /**< fru id subsection included */
+    uint32_t    fru_subscn_included;
 
-    char	priority;               /**< fru priority */
+    char	priority;             /**< fru priority */
 #define RTAS_FRU_PRIORITY_HIGH      'H'
 #define RTAS_FRU_PRIORITY_MEDIUM    'M'
 #define RTAS_FRU_PRIORITY_MEDIUM_A  'A'
@@ -358,12 +391,20 @@ struct rtas_fru_scn {
 #define RTAS_FRU_PRIORITY_MEDIUM_C  'C'
 #define RTAS_FRU_PRIORITY_LOW       'L'
 
-    uint32_t    loc_code_length:8;      /**< location field length */
-    char        loc_code[80];           /**< location code */
+    uint32_t    loc_code_length;      /**< location field length */
+    char        loc_code[80];         /**< location code */
     struct rtas_fru_scn *next;
     struct rtas_fru_hdr *subscns;
 };
 
+struct rtas_fru_scn_raw {
+    uint32_t    length:8;
+    uint32_t	data1:8;
+    char	priority;
+    uint32_t    loc_code_length:8;
+    char        loc_code[80];
+};
+
 #define RE_FRU_SCN_SZ       4
 
 /**
@@ -372,31 +413,54 @@ struct rtas_fru_scn {
  */
 struct rtas_src_scn {
     struct scn_header shdr;
-    struct rtas_v6_hdr_raw v6hdr;
+    struct rtas_v6_hdr v6hdr;
 
-    uint32_t    version:8;          /**< SRC version */ 
-    char        src_platform_data[7];   /**< platform specific data */
+    uint32_t    version;              /**< SRC version */ 
+    char        src_platform_data[7]; /**< platform specific data */
 #define src_subscns_included(src)    ((src)->src_platform_data[0] & 0x01)
 
-    uint32_t    ext_refcode2:32;    /**< extended reference code word 2 */
-    uint32_t    ext_refcode3:32;    /**< extended reference code word 3 */
-    uint32_t    ext_refcode4:32;    /**< extended reference code word 4 */
-    uint32_t    ext_refcode5:32;    /**< extended reference code word 5 */
+    uint32_t    ext_refcode2;         /**< extended reference code word 2 */
+    uint32_t    ext_refcode3;         /**< extended reference code word 3 */
+    uint32_t    ext_refcode4;         /**< extended reference code word 4 */
+    uint32_t    ext_refcode5;         /**< extended reference code word 5 */
 
-    uint32_t    ext_refcode6:32;    /**< extended reference code word 6 */
-    uint32_t    ext_refcode7:32;    /**< extended reference code word 7 */
-    uint32_t    ext_refcode8:32;    /**< extended reference code word 8 */
-    uint32_t    ext_refcode9:32;    /**< extended reference code word 9 */
+    uint32_t    ext_refcode6;         /**< extended reference code word 6 */
+    uint32_t    ext_refcode7;         /**< extended reference code word 7 */
+    uint32_t    ext_refcode8;         /**< extended reference code word 8 */
+    uint32_t    ext_refcode9;         /**< extended reference code word 9 */
 
-    char        primary_refcode[36];/**< primary reference code */
+    char        primary_refcode[36];  /**< primary reference code */
     
-    uint32_t    subscn_id:8;		    /**< sub-section id (0xC0) */
-    uint32_t    subscn_platform_data:8;    /**< platform specific data */
-    uint32_t    subscn_length:16;   /**< sub-section length */
+    uint32_t    subscn_id;	      /**< sub-section id (0xC0) */
+    uint32_t    subscn_platform_data; /**< platform specific data */
+    uint32_t    subscn_length;        /**< sub-section length */
 
     struct rtas_fru_scn *fru_scns;
 };
 
+struct rtas_src_scn_raw {
+    struct rtas_v6_hdr_raw v6hdr;
+
+    uint32_t    version:8;
+    char        src_platform_data[7];
+
+    uint32_t    ext_refcode2:32;
+    uint32_t    ext_refcode3:32;
+    uint32_t    ext_refcode4:32;
+    uint32_t    ext_refcode5:32;
+
+    uint32_t    ext_refcode6:32;
+    uint32_t    ext_refcode7:32;
+    uint32_t    ext_refcode8:32;
+    uint32_t    ext_refcode9:32;
+
+    char        primary_refcode[36];
+    
+    uint32_t    subscn_id:8;
+    uint32_t    subscn_platform_data:8;
+    uint32_t    subscn_length:16;
+};
+
 #define RE_SRC_SCN_SZ       80
 #define RE_SRC_SUBSCN_SZ    4
 
diff --git a/librtasevent_src/rtas_srcfru.c b/librtasevent_src/rtas_srcfru.c
index c757999..1fb1840 100644
--- a/librtasevent_src/rtas_srcfru.c
+++ b/librtasevent_src/rtas_srcfru.c
@@ -19,6 +19,23 @@
 #include "rtas_src_codes.c"
 
 /**
+ * parse_fru_hdr
+ * @brief Parse the ontents of a FRU header
+ *
+ * @param fru_hdr rtas_fru_hdr pointer
+ * @param fru_hdr_raw rtas_fru_hdr_raw pointer
+ */
+static void parse_fru_hdr(struct rtas_fru_hdr *fru_hdr,
+			  struct rtas_fru_hdr_raw *fru_hdr_raw)
+{
+    fru_hdr->id[0] = fru_hdr_raw->id[0];
+    fru_hdr->id[1] = fru_hdr_raw->id[1];
+
+    fru_hdr->length = fru_hdr_raw->length;
+    fru_hdr->flags = fru_hdr_raw->flags;
+}
+
+/**
  * parse_fru_id_scn
  * @brief Parse a FRU Identity Substructure
  *
@@ -29,6 +46,7 @@ static struct rtas_fru_hdr *
 parse_fru_id_scn(struct rtas_event *re)
 {
     struct rtas_fru_id_scn *fru_id;
+    struct rtas_fru_id_scn_raw *fru_id_raw;
 
     fru_id = malloc(sizeof(*fru_id));
     if (fru_id == NULL) {
@@ -37,7 +55,10 @@ parse_fru_id_scn(struct rtas_event *re)
     }
 
     memset(fru_id, 0, sizeof(*fru_id));
-    rtas_copy(RE_FRU_HDR_OFFSET(fru_id), re, RE_FRU_HDR_SZ);
+
+    fru_id_raw = (struct rtas_fru_id_scn_raw *)re->buffer + re->offset;
+    parse_fru_hdr(&fru_id->fruhdr, &fru_id_raw->fruhdr);
+    re->offset += RE_FRU_HDR_SZ;
 
     if (fruid_has_part_no(fru_id)) {
         strcpy(fru_id->part_no, RE_EVENT_OFFSET(re));
@@ -73,6 +94,7 @@ static struct rtas_fru_hdr *
 parse_fru_pe_scn(struct rtas_event *re)
 {
     struct rtas_fru_pe_scn *fru_pe;
+    struct rtas_fru_pe_scn_raw *fru_pe_raw;
     uint32_t scn_sz;
     char *data;
 
@@ -83,7 +105,9 @@ parse_fru_pe_scn(struct rtas_event *re)
     }
 
     memset(fru_pe, 0, sizeof(*fru_pe));
-    rtas_copy(RE_FRU_HDR_OFFSET(fru_pe), re, RE_FRU_HDR_SZ);
+    fru_pe_raw = (struct rtas_fru_pe_scn_raw *)re->buffer + re->offset;
+    parse_fru_hdr(&fru_pe->fruhdr, &fru_pe_raw->fruhdr);
+    re->offset += RE_FRU_HDR_SZ;
 
     scn_sz = fru_pe->fruhdr.length;
     data = (char *)fru_pe + sizeof(fru_pe->fruhdr);
@@ -104,8 +128,8 @@ static struct rtas_fru_hdr *
 parse_fru_mr_scn(struct rtas_event *re)
 {
     struct rtas_fru_mr_scn *fru_mr;
-    uint32_t scn_sz;
-    char *data;
+    struct rtas_fru_mr_scn_raw *fru_mr_raw;
+    int i, mrus_sz, num_mrus;
 
     fru_mr = malloc(sizeof(*fru_mr));
     if (fru_mr == NULL) {
@@ -114,16 +138,39 @@ parse_fru_mr_scn(struct rtas_event *re)
     }
 
     memset(fru_mr, 0, sizeof(*fru_mr));
-    rtas_copy(RE_FRU_HDR_OFFSET(fru_mr), re, RE_FRU_HDR_SZ);
+    fru_mr_raw = (struct rtas_fru_mr_scn_raw *)re->buffer + re->offset;
+    parse_fru_hdr(&fru_mr->fruhdr, &fru_mr_raw->fruhdr);
+    re->offset += RE_FRU_HDR_SZ;
 
-    scn_sz = fru_mr->fruhdr.length;
-    data = (char *)fru_mr + sizeof(fru_mr->fruhdr);
-    
-    rtas_copy(data, re, scn_sz - RE_FRU_HDR_SZ);
+    mrus_sz = fru_mr->fruhdr.length - RE_FRU_HDR_SZ - sizeof(uint32_t);
+    num_mrus = mrus_sz / sizeof(struct fru_mru_raw);
+
+    for (i = 0; i < num_mrus; i++) {
+	fru_mr->mrus[i].priority = fru_mr_raw->mrus[i].priority;
+	fru_mr->mrus[i].id = be32toh(fru_mr_raw->mrus[i].id);
+    }
 
+    re->offset += mrus_sz + sizeof(uint32_t) /* reserved piece */; 
     return (struct rtas_fru_hdr *)fru_mr;
 }
 
+void parse_fru_scn(struct rtas_event *re, struct rtas_fru_scn *fru,
+		   struct rtas_fru_scn_raw *rawfru)
+{
+    fru->length = rawfru->length;
+
+    fru->type = (rawfru->data1 & 0xf0) >> 4;
+    fru->fru_id_included = (rawfru->data1 & 0x08) >> 3;
+    fru->fru_subscn_included = rawfru->data1 & 0x07;
+
+    fru->priority = rawfru->priority;
+    fru->loc_code_length = rawfru->loc_code_length;
+    re->offset += RE_FRU_SCN_SZ;
+
+    memcpy(fru->loc_code, rawfru->loc_code, fru->loc_code_length);
+    re->offset += fru->loc_code_length;
+}
+
 /**
  * parse_v6_src_scn
  * @brief parse a version 6 rtas SRC section
@@ -136,6 +183,7 @@ int
 parse_src_scn(struct rtas_event *re)
 {
     struct rtas_src_scn *src;
+    struct rtas_src_scn_raw *src_raw;
     struct rtas_fru_scn *fru, *last_fru;
     int total_len, srcsub_len;
 
@@ -148,13 +196,36 @@ parse_src_scn(struct rtas_event *re)
     memset(src, 0, sizeof(*src));
     src->shdr.raw_offset = re->offset;
 
-    rtas_copy(RE_SHDR_OFFSET(src), re, RE_SRC_SCN_SZ);
-    add_re_scn(re, src, re_scn_id(&src->v6hdr));
+    src_raw = (struct rtas_src_scn_raw *)(re->buffer + re->offset);
+    parse_v6_hdr(&src->v6hdr, &src_raw->v6hdr);
 
-    if (! src_subscns_included(src))
+    src->version = src_raw->version;
+    memcpy(&src->src_platform_data, &src_raw->src_platform_data,
+	   sizeof(src->src_platform_data));
+
+    src->ext_refcode2 = be32toh(src_raw->ext_refcode2);
+    src->ext_refcode3 = be32toh(src_raw->ext_refcode3);
+    src->ext_refcode4 = be32toh(src_raw->ext_refcode4);
+    src->ext_refcode5 = be32toh(src_raw->ext_refcode5);
+    
+    src->ext_refcode6 = be32toh(src_raw->ext_refcode6);
+    src->ext_refcode7 = be32toh(src_raw->ext_refcode7);
+    src->ext_refcode8 = be32toh(src_raw->ext_refcode8);
+    src->ext_refcode9 = be32toh(src_raw->ext_refcode9);
+
+    memcpy(&src->primary_refcode, &src_raw->primary_refcode,
+	   sizeof(src->primary_refcode));
+
+    re->offset += RE_SRC_SCN_SZ;
+    add_re_scn(re, src, re_scn_id(&src_raw->v6hdr));
+
+    if (!src_subscns_included(src))
         return 0;
 
-    rtas_copy(RE_SHDR_OFFSET(src) + RE_SRC_SCN_SZ + 4, re, RE_SRC_SUBSCN_SZ);
+    src->subscn_id = src_raw->subscn_id;
+    src->subscn_platform_data = src_raw->subscn_platform_data;
+    src->subscn_length = be16toh(src_raw->subscn_length);
+    re->offset += RE_SRC_SUBSCN_SZ;
 
     srcsub_len = src->subscn_length * 4; /*get number of bytes */
     total_len = RE_SRC_SUBSCN_SZ;
@@ -164,6 +235,7 @@ parse_src_scn(struct rtas_event *re)
     do {
 	uint32_t fru_len, fru_end;
 	struct rtas_fru_hdr *last_fruhdr = NULL;
+	struct rtas_fru_scn_raw *rawfru;
 	
         fru = malloc(sizeof(*fru));
         if (fru == NULL) {
@@ -174,11 +246,8 @@ parse_src_scn(struct rtas_event *re)
 
         memset(fru, 0, sizeof(*fru));
         
-        /* First the fixed part of the fru */
-        rtas_copy(fru, re, RE_FRU_SCN_SZ);
-        
-        /* Then the variable length location string */
-        rtas_copy(fru->loc_code, re, fru->loc_code_length);
+	rawfru = (struct rtas_fru_scn_raw *)(re->buffer + re->offset);
+	parse_fru_scn(re, fru, rawfru);
 
 	fru_len = RE_FRU_SCN_SZ + fru->loc_code_length;
         fru_end = re->offset + fru->length - fru_len;
