summaryrefslogtreecommitdiffstats
path: root/core/vpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/vpd.c')
-rw-r--r--core/vpd.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/core/vpd.c b/core/vpd.c
index 0e6f83ba..85a99373 100644
--- a/core/vpd.c
+++ b/core/vpd.c
@@ -115,9 +115,15 @@ const void *vpd_find(const void *vpd, size_t vpd_size,
return p;
}
+static void *vpd;
+static size_t vpd_size;
+static uint32_t vpd_lid_no;
+
/* Helper to load a VPD LID. Pass a ptr to the corresponding LX keyword */
-static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size)
+static void *vpd_lid_preload(const uint8_t *lx)
{
+ int rc;
+
/* Now this is a guess game as we don't have the info from the
* pHyp folks. But basically, it seems to boil down to loading
* a LID whose name is 0x80e000yy where yy is the last 2 digits
@@ -130,44 +136,71 @@ static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size)
* For safety, we look for a matching LX record in an LXRn
* (n = lxrn argument) or in VINI if lxrn=0xff
*/
- uint32_t lid_no = 0x80e00000 | ((lx[6] & 0xf) << 8) | lx[7];
+ vpd_lid_no = 0x80e00000 | ((lx[6] & 0xf) << 8) | lx[7];
/* We don't quite know how to get to the LID directory so
* we don't know the size. Let's allocate 16K. All the VPD LIDs
* I've seen so far are much smaller.
*/
#define VPD_LID_MAX_SIZE 0x4000
- void *data = malloc(VPD_LID_MAX_SIZE);
- char record[4] = "LXR0";
- const void *valid_lx;
- uint8_t lx_size;
- int rc;
+ vpd = malloc(VPD_LID_MAX_SIZE);
- if (!data) {
+ if (!vpd) {
prerror("VPD: Failed to allocate memory for LID\n");
return NULL;
}
/* Adjust LID number for flash side */
- lid_no = fsp_adjust_lid_side(lid_no);
- printf("VPD: Trying to load VPD LID 0x%08x...\n", lid_no);
+ vpd_lid_no = fsp_adjust_lid_side(vpd_lid_no);
+ printf("VPD: Trying to load VPD LID 0x%08x...\n", vpd_lid_no);
- *size = VPD_LID_MAX_SIZE;
+ vpd_size = VPD_LID_MAX_SIZE;
/* Load it from the FSP */
- rc = fsp_load_lid(lid_no, data, size);
+ rc = fsp_preload_lid(vpd_lid_no, vpd, &vpd_size);
if (rc) {
prerror("VPD: Error %d loading VPD LID\n", rc);
goto fail;
}
+ return vpd;
+ fail:
+ free(vpd);
+ return NULL;
+}
+
+void vpd_iohub_load(struct dt_node *hub_node)
+{
+ char record[4] = "LXR0";
+ const void *valid_lx;
+ uint8_t lx_size;
+ int r;
+ const uint32_t *p;
+ const uint8_t *lx;
+ unsigned int lxrn;
+
+ p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL);
+ if (!p)
+ return;
+
+ lxrn = p[0];
+ lx = (const char *)&p[1];
+
+ assert(vpd);
+ assert(vpd_lid_no);
+
+ r = fsp_wait_lid_loaded(vpd_lid_no);
+
+ if (r)
+ goto fail;
+
/* Validate it */
if (lxrn < 9)
record[3] = '0' + lxrn;
else
memcpy(record, "VINI", 4);
- valid_lx = vpd_find(data, *size, record, "LX", &lx_size);
+ valid_lx = vpd_find(vpd, vpd_size, record, "LX", &lx_size);
if (!valid_lx || lx_size != 8) {
prerror("VPD: Cannot find validation LX record\n");
goto fail;
@@ -177,35 +210,35 @@ static void *vpd_lid_load(const uint8_t *lx, uint8_t lxrn, size_t *size)
goto fail;
}
- printf("VPD: Loaded %zu bytes\n", *size);
+ printf("VPD: Loaded %zu bytes\n", vpd_size);
/* Got it ! */
- return realloc(data, *size);
- fail:
- free(data);
- return NULL;
+ vpd = realloc(vpd, vpd_size);
+
+ if (!vpd)
+ goto fail;
+
+ dt_add_property(hub_node, "ibm,io-vpd", vpd, vpd_size);
+ free(vpd);
+ return;
+
+fail:
+ free(vpd);
+ vpd = NULL;
+ prerror("VPD: Failed to load VPD LID\n");
+ return;
}
-void vpd_iohub_load(struct dt_node *hub_node)
+void vpd_preload(struct dt_node *hub_node)
{
- void *vpd;
- size_t sz;
const uint32_t *p;
- unsigned int lx_idx;
const char *lxr;
p = dt_prop_get_def(hub_node, "ibm,vpd-lx-info", NULL);
if (!p)
return;
- lx_idx = p[0];
lxr = (const char *)&p[1];
- vpd = vpd_lid_load(lxr, lx_idx, &sz);
- if (!vpd) {
- prerror("VPD: Failed to load VPD LID\n");
- } else {
- dt_add_property(hub_node, "ibm,io-vpd", vpd, sz);
- free(vpd);
- }
+ vpd = vpd_lid_preload(lxr);
}
OpenPOWER on IntegriCloud