/** * parse_v6_rtas_event * @brief parse a version 6 RTAS event * * @param re rtas_event pointer * @return rtas_event pointer on success, NULL on failure */ struct rtas_event * parse_v6_rtas_event(struct rtas_event *re) { struct rtas_v6_hdr *v6hdr; char *ibm; ibm = re->buffer + re->offset; /* Sanity Check for "IBM" string */ if (strncmp(ibm, "IBM", 3) != 0) { cleanup_rtas_event(re); errno = EFAULT; return NULL; } re->offset += 4; /* IBM + NULL */ if (parse_priv_hdr_scn(re) != 0) { cleanup_rtas_event(re); return NULL; } if (parse_usr_hdr_scn(re) != 0) { cleanup_rtas_event(re); return NULL; } while (re->offset < re->event_length) { int scn_id, rc; v6hdr = (struct rtas_v6_hdr *)(re->buffer + re->offset); scn_id = re_scn_id(v6hdr); switch (scn_id) { case RTAS_EPOW_SCN: rc = parse_epow_scn(re); break; case RTAS_IO_SCN: rc = parse_io_scn(re); break; case RTAS_DUMP_SCN: rc = parse_dump_scn(re); break; case RTAS_LRI_SCN: rc = parse_lri_scn(re); break; case RTAS_MT_SCN: rc = parse_mt_scn(re); break; case RTAS_PSRC_SCN: case RTAS_SSRC_SCN: rc = parse_src_scn(re); break; default: rc = parse_generic_v6_scn(re); break; } if (rc) { cleanup_rtas_event(re); re = NULL; break; } } return re; }
int parse_opal_event_log(char *buf, int buflen, struct opal_event_log_scn **r_log) { struct header_id elog_hdr_id[] = { HEADER_ORDER }; int rc; struct opal_v6_hdr hdr; struct opal_priv_hdr_scn *ph; int header_pos; struct header_id *hdr_data; char *start = buf; int nrsections = 0; int is_error = 0; int i; opal_event_log *log = NULL; int log_pos = 0; *r_log = NULL; while (buflen) { rc = parse_section_header(&hdr, buf, buflen); if (rc < 0) { break; } header_pos = header_id_lookup(elog_hdr_id, HEADER_ORDER_MAX, hdr.id); if (header_pos == -1) { printf("Unknown section header: %c%c at %lu:\n", hdr.id[0], hdr.id[1], buf-start); printf("Length: %u (incl 8 byte header)\n", hdr.length); printf("Hex:\n"); for (i = 8; i < hdr.length; i++) { printf("0x%02x ", *(buf+i)); if (i % 16) printf("\n"); } printf("Text (. = unprintable):\n"); for (i = 8; i < hdr.length; i++) { printf("%c", (isgraph(*(buf+i)) | isspace(*(buf+i))) ? *(buf+i) : '.'); } } hdr_data = &elog_hdr_id[header_pos]; nrsections++; if (hdr_data->pos != 0 && hdr_data->pos != nrsections && ((hdr_data->req & HEADER_REQ) || ((hdr_data->req & HEADER_REQ_W_ERROR) && is_error))) { fprintf(stderr, "ERROR %s: Section number %d should be " "%s, instead is 0x%02x%02x (%c%c)\n", __func__, nrsections, hdr_data->id, hdr.id[0], hdr.id[1], hdr.id[0], hdr.id[1]); rc = -1; break; } if (hdr_data->max == 0) { fprintf(stderr, "ERROR %s: Section %s has already appeared the " "required times and should not be seen again\n", __func__, hdr_data->id); } else if (hdr_data->max > 0) { hdr_data->max--; } if (strncmp(hdr.id, "PH", 2) == 0) { if (parse_priv_hdr_scn(&ph, &hdr, buf, buflen) == 0) { log = create_opal_event_log(ph->scn_count); if (!log) { free(ph); fprintf(stderr, "ERROR %s: Could not allocate internal log buffer\n", __func__); return -ENOMEM; } add_opal_event_log_scn(log, "PH", ph, log_pos++); } else { /* We didn't parse the private header and therefore couldn't malloc * the log array, must stop */ fprintf(stderr, "ERROR %s: Unable to parse private header section" " cannot continue\n", __func__); return -EINVAL; } } else if (strncmp(hdr.id, "UH", 2) == 0) { struct opal_usr_hdr_scn *usr; if (parse_usr_hdr_scn(&usr, &hdr, buf, buflen, &is_error) == 0) { add_opal_event_log_scn(log, "UH", usr, log_pos++); } } else if (strncmp(hdr.id, "PS", 2) == 0) { struct opal_src_scn *src; if (parse_src_scn(&src, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "PS", src, log_pos++); } } else if (strncmp(hdr.id, "EH", 2) == 0) { struct opal_eh_scn *eh; if (parse_eh_scn(&eh, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "EH", eh, log_pos++); } } else if (strncmp(hdr.id, "MT", 2) == 0) { struct opal_mtms_scn *mtms; if (parse_mtms_scn(&mtms, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "MT", mtms, log_pos++); } } else if (strncmp(hdr.id, "SS", 2) == 0) { struct opal_src_scn *src; if (parse_src_scn(&src, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "SS", src, log_pos++); } } else if (strncmp(hdr.id, "DH", 2) == 0) { struct opal_dh_scn *dh; if (parse_dh_scn(&dh, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "DH", dh, log_pos++); } } else if (strncmp(hdr.id, "SW", 2) == 0) { struct opal_sw_scn *sw; if (parse_sw_scn(&sw, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "SW", sw, log_pos++); } } else if (strncmp(hdr.id, "LP", 2) == 0) { struct opal_lp_scn *lp; if (parse_lp_scn(&lp, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "LP", lp, log_pos++); } } else if (strncmp(hdr.id, "LR", 2) == 0) { struct opal_lr_scn *lr; if (parse_lr_scn(&lr, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "LR", lr, log_pos++); } } else if (strncmp(hdr.id, "HM", 2) == 0) { struct opal_hm_scn *hm; if (parse_hm_scn(&hm, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "HM", hm, log_pos++); } } else if (strncmp(hdr.id, "EP", 2) == 0) { struct opal_ep_scn *ep; if (parse_ep_scn(&ep, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "EP", ep, log_pos++); } } else if (strncmp(hdr.id, "IE", 2) == 0) { struct opal_ie_scn *ie; if (parse_ie_scn(&ie, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "IE", ie, log_pos++); } } else if (strncmp(hdr.id, "MI", 2) == 0) { struct opal_mi_scn *mi; if (parse_mi_scn(&mi, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "MI", mi, log_pos++); } } else if (strncmp(hdr.id, "CH", 2) == 0) { struct opal_ch_scn *ch; if (parse_ch_scn(&ch, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "CH", ch, log_pos++); } } else if (strncmp(hdr.id, "UD", 2) == 0) { struct opal_ud_scn *ud; if (parse_ud_scn(&ud, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "UD", ud, log_pos++); } } else if (strncmp(hdr.id, "EI", 2) == 0) { struct opal_ei_scn *ei; if (parse_ei_scn(&ei, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "EI", ei, log_pos++); } } else if (strncmp(hdr.id, "ED", 2) == 0) { struct opal_ed_scn *ed; if (parse_ed_scn(&ed, &hdr, buf, buflen) == 0) { add_opal_event_log_scn(log, "ED", ed, log_pos++); } } buf += hdr.length; if (nrsections == ph->scn_count) break; } if(log) { /* we could get here but have failed to parse sections of have an * unexpectady truncated buffer pad log with NULLS */ char nulStr2[2] = {'\0','\0'}; for(i = log_pos; i < ph->scn_count; i++) { add_opal_event_log_scn(log, nulStr2, NULL, i); } *r_log = log; } for (i = 0; i < HEADER_ORDER_MAX; i++) { if (((elog_hdr_id[i].req & HEADER_REQ) || ((elog_hdr_id[i].req & HEADER_REQ_W_ERROR) && is_error)) && elog_hdr_id[i].max != 0) { fprintf(stderr,"ERROR %s: Truncated error log, expected section %s" " not found\n", __func__, elog_hdr_id[i].id); rc = -EINVAL; } } return rc; }