Exemple #1
0
/**
 * 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;
}