/** * parse_v6_src_scn * @brief parse a version 6 rtas SRC section * * @param re rtas_event pointer * @param src_start pointer to beginning of SRC section * @return 0 on success, !0 on failure */ 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; src = malloc(sizeof(*src)); if (src == NULL) { errno = ENOMEM; return 1; } src_raw = malloc(sizeof(*src_raw)); if (src_raw == NULL) { errno = ENOMEM; return 1; } memset(src, 0, sizeof(*src)); memset(src_raw, 0, sizeof(*src_raw)); src->shdr.raw_offset = re->offset; rtas_copy(src_raw, re, RE_SRC_SCN_SZ); parse_v6_hdr(&src->v6hdr, &src_raw->v6hdr); 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)); add_re_scn(re, src, re_scn_id(&src_raw->v6hdr)); if (!src_subscns_included(src)) return 0; rtas_copy( (char *) src_raw + 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); srcsub_len = src->subscn_length * 4; /*get number of bytes */ total_len = RE_SRC_SUBSCN_SZ; last_fru = NULL; 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) { cleanup_rtas_event(re); errno = ENOMEM; return 1; } memset(fru, 0, sizeof(*fru)); 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; while (re->offset < fru_end) { struct rtas_fru_hdr *cur_fruhdr = NULL; char *id = re->buffer + re->offset; if (strncmp(id, "ID", 2) == 0) cur_fruhdr = parse_fru_id_scn(re); else if (strncmp(id, "PE", 2) == 0) cur_fruhdr = parse_fru_pe_scn(re); else if (strncmp(id, "MR", 2) == 0) cur_fruhdr = parse_fru_mr_scn(re); else { re->offset++; continue; } if (cur_fruhdr == NULL) { cleanup_rtas_event(re); return -1; } if (last_fruhdr == NULL) fru->subscns = cur_fruhdr; else last_fruhdr->next = cur_fruhdr; last_fruhdr = cur_fruhdr; } if (last_fru == NULL) src->fru_scns = fru; else last_fru->next = fru; last_fru = fru; total_len += fru->length; } while (total_len < srcsub_len); return 0; }
int parse_src_scn(struct opal_src_scn **r_src, const struct opal_v6_hdr *hdr, const char *buf, int buflen) { struct opal_src_scn *bufsrc = (struct opal_src_scn*)buf; struct opal_src_scn *src; int offset = OPAL_SRC_SCN_STATIC_SIZE; int error = check_buflen(buflen, offset, __func__); if (error) return error; /* header length can be > sizeof() as is variable sized section * subtract the size of the optional section */ if (hdr->length < offset) { fprintf(stderr, "%s: section header length less than min size " ". section header length %u, min size: %u\n", __func__, hdr->length, offset); return -EINVAL; } *r_src = malloc(sizeof(struct opal_src_scn)); if(!*r_src) return -ENOMEM; src = *r_src; src->v6hdr = *hdr; src->version = bufsrc->version; src->flags = bufsrc->flags; src->wordcount = bufsrc->wordcount; src->srclength = be16toh(bufsrc->srclength); src->ext_refcode2 = be32toh(bufsrc->ext_refcode2); src->ext_refcode3 = be32toh(bufsrc->ext_refcode3); src->ext_refcode4 = be32toh(bufsrc->ext_refcode4); src->ext_refcode5 = be32toh(bufsrc->ext_refcode5); src->ext_refcode6 = be32toh(bufsrc->ext_refcode6); src->ext_refcode7 = be32toh(bufsrc->ext_refcode7); src->ext_refcode8 = be32toh(bufsrc->ext_refcode8); src->ext_refcode9 = be32toh(bufsrc->ext_refcode9); memcpy(src->primary_refcode, bufsrc->primary_refcode, OPAL_SRC_SCN_PRIMARY_REFCODE_LEN); src->fru_count = 0; if (src->flags & OPAL_SRC_ADD_SCN) { error = check_buflen(buflen, offset + sizeof(struct opal_src_add_scn_hdr), __func__); if (error) { free(src); return error; } src->addhdr.flags = bufsrc->addhdr.flags; src->addhdr.id = bufsrc->addhdr.id; if (src->addhdr.id != OPAL_FRU_SCN_ID) { fprintf(stderr, "%s: invalid section id, expecting 0x%x but found" " 0x%x", __func__, OPAL_FRU_SCN_ID, src->addhdr.id); free(src); return -EINVAL; } src->addhdr.length = be16toh(bufsrc->addhdr.length); offset += sizeof(struct opal_src_add_scn_hdr); while(offset < src->srclength && src->fru_count < OPAL_SRC_FRU_MAX) { error = parse_fru_scn(&(src->fru[src->fru_count]), buf + offset, buflen - offset); if (error < 0) { free(src); return error; } offset += error; src->fru_count++; } } return 0; }