diff options
Diffstat (limited to 'core/vpd.c')
-rw-r--r-- | core/vpd.c | 93 |
1 files changed, 63 insertions, 30 deletions
@@ -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); } |