/* Locate a keyword in a record in a VPD blob * * Note: This works with VPD LIDs. It will scan until it finds * the first 0x84, so it will skip all those 0's that the VPD * LIDs seem to contain */ const void *vpd_find(const void *vpd, size_t vpd_size, const char *record, const char *keyword, uint8_t *sz) { size_t rec_sz; const uint8_t *p; p = vpd_find_record(vpd, vpd_size, record, &rec_sz); if (p) p = vpd_find_keyword(p, rec_sz, keyword, sz); return p; }
void lxvpd_process_slot_entries(struct phb *phb, struct dt_node *node, uint8_t chip_id, uint8_t index, uint32_t slot_size) { const void *lxvpd; const uint8_t *pr_rec, *pr_end, *sm; size_t lxvpd_size, pr_size; const uint16_t *mf = NULL; char record[5] = "PR00"; uint8_t mf_sz, sm_sz; bool found = false; record[2] += chip_id; record[3] += index; record[4] = 0; /* Get LX VPD pointer */ lxvpd = dt_prop_get_def_size(node, "ibm,io-vpd", NULL, &lxvpd_size); if (!lxvpd) { prlog(PR_WARNING, "No data found for PHB%04x %s\n", phb->opal_id, record); return; } pr_rec = vpd_find_record(lxvpd, lxvpd_size, record, &pr_size); if (!pr_rec) { prlog(PR_WARNING, "Record %s not found on PHB%04x\n", record, phb->opal_id); return; } /* As long as there's still something in the PRxy record */ prlog(PR_DEBUG, "PHB%04x record %s has %ld bytes\n", phb->opal_id, record, pr_size); pr_end = pr_rec + pr_size; while (pr_rec < pr_end) { pr_size = pr_end - pr_rec; /* Find the next MF keyword */ mf = vpd_find_keyword(pr_rec, pr_size, "MF", &mf_sz); /* And the corresponding SM */ sm = vpd_find_keyword(pr_rec, pr_size, "SM", &sm_sz); if (!mf || !sm) { if (!found) prlog(PR_WARNING, "Slot Map keyword %s not found\n", record); return; } prlog(PR_DEBUG, "Found 0x%04x map...\n", *mf); switch (*mf) { case 0x1004: lxvpd_parse_1004_map(phb, sm + 1, sm_sz - 1, slot_size); found = true; break; case 0x1005: lxvpd_parse_1005_map(phb, sm + 1, sm_sz - 1, slot_size); found = true; break; /* Add support for 0x1006 maps ... */ } pr_rec = sm + sm_sz; } }