static int unum_contains_bypat(const char *erunum, const char *eeunum) { char **ernms, **eenms; size_t nernms, neenms; int i, j, rv = 1; if (mem_unum_burst(erunum, &ernms, &nernms) < 0) return (fmd_fmri_set_errno(EINVAL)); if (mem_unum_burst(eeunum, &eenms, &neenms) < 0) { mem_strarray_free(ernms, nernms); return (fmd_fmri_set_errno(EINVAL)); } for (i = 0; i < neenms; i++) { for (j = 0; j < nernms; j++) { if (strcmp(eenms[i], ernms[j]) == 0) break; } if (j == nernms) { /* * This DIMM was not found in the container. */ rv = 0; break; } } mem_strarray_free(ernms, nernms); mem_strarray_free(eenms, neenms); return (rv); }
ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { int err; ssize_t len; topo_hdl_t *thp; char *str; if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); if (topo_fmri_nvl2str(thp, nvl, &str, &err) != 0) { fmd_fmri_topo_rele(thp); return (fmd_fmri_set_errno(EINVAL)); } if (buf != NULL) len = snprintf(buf, buflen, "%s", str); else len = strlen(str); topo_hdl_strfree(thp, str); fmd_fmri_topo_rele(thp); return (len); }
int fmd_fmri_unusable(nvlist_t *nvl) { int rc, err = 0; uint8_t version; uint32_t cpuid; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_CPU_SCHEME_VERSION || nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) return (fmd_fmri_set_errno(EINVAL)); /* * If the cpu-scheme topology exports this method unusable(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_unusable(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != ETOPO_METHOD_NOTSUP) return (rc); return (p_online(cpuid, P_STATUS) == P_FAULTED); }
static int cpu_get_serialid_kstat(uint32_t cpuid, uint64_t *serialidp) { kstat_named_t *kn; kstat_ctl_t *kc; kstat_t *ksp; int i; if ((kc = kstat_open()) == NULL) return (-1); /* errno is set for us */ if ((ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL)) == NULL) { (void) kstat_close(kc); return (fmd_fmri_set_errno(ENOENT)); } if (kstat_read(kc, ksp, NULL) == -1) { int oserr = errno; (void) kstat_close(kc); return (fmd_fmri_set_errno(oserr)); } for (kn = ksp->ks_data, i = 0; i < ksp->ks_ndata; i++, kn++) { if (strcmp(kn->name, "device_ID") == 0) { *serialidp = kn->value.ui64; (void) kstat_close(kc); return (0); } } (void) kstat_close(kc); return (fmd_fmri_set_errno(ENOENT)); }
int fmd_fmri_replaced(nvlist_t *nvl) { int rc, err = 0; uint8_t version; uint32_t cpuid; uint64_t nvlserid, curserid; char *nvlserstr, curserbuf[21]; /* sizeof (UINT64_MAX) + '\0' */ topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) return (fmd_fmri_set_errno(EINVAL)); /* * If the cpu-scheme topology exports this method replaced(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_replaced(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != ETOPO_METHOD_NOTSUP) return (rc); if (version == CPU_SCHEME_VERSION0) { if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, &nvlserid) != 0) return (fmd_fmri_set_errno(EINVAL)); if (cpu_get_serialid_V0(cpuid, &curserid) != 0) return (errno == ENOENT ? FMD_OBJ_STATE_NOT_PRESENT : -1); return (curserid == nvlserid ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_REPLACED); } else if (version == CPU_SCHEME_VERSION1) { if ((rc = nvlist_lookup_string(nvl, FM_FMRI_CPU_SERIAL_ID, &nvlserstr)) != 0) if (rc != ENOENT) return (fmd_fmri_set_errno(EINVAL)); /* * If serial id is not available, just check if the cpuid * is present. */ if (cpu_get_serialid_V1(cpuid, curserbuf, 21) != 0) if (cpu_cpuid_present(cpuid)) return (FMD_OBJ_STATE_UNKNOWN); else return (FMD_OBJ_STATE_NOT_PRESENT); return (strcmp(curserbuf, nvlserstr) == 0 ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_REPLACED); } else { return (fmd_fmri_set_errno(EINVAL)); } }
static int fru_compare(nvlist_t *r1, nvlist_t *r2) { topo_hdl_t *thp; nvlist_t *f1 = NULL, *f2 = NULL; nvlist_t **h1 = NULL, **h2 = NULL; uint_t h1sz, h2sz; int err, rc = 1; if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); (void) topo_fmri_fru(thp, r1, &f1, &err); (void) topo_fmri_fru(thp, r2, &f2, &err); if (f1 != NULL && f2 != NULL) { (void) nvlist_lookup_nvlist_array(f1, FM_FMRI_HC_LIST, &h1, &h1sz); (void) nvlist_lookup_nvlist_array(f2, FM_FMRI_HC_LIST, &h2, &h2sz); if (h1sz == h2sz && hclist_contains(h1, h1sz, h2, h2sz) == 1) rc = 0; } fmd_fmri_topo_rele(thp); if (f1 != NULL) nvlist_free(f1); if (f2 != NULL) nvlist_free(f2); return (rc); }
static int unum_contains_bysubstr(const char *erunum, const char *eeunum) { uint_t erlen, eelen; int nojnumstrip = 0; /* * This comparison method is only known to work on specific types of * unums. Check for those types here. */ if ((strncmp(erunum, "/N", 2) != 0 && strncmp(erunum, "/IO", 3) != 0 && strncmp(erunum, "/SB", 3) != 0) || (strncmp(eeunum, "/N", 2) != 0 && strncmp(eeunum, "/IO", 3) != 0 && strncmp(eeunum, "/SB", 3) != 0)) { if (ISHCUNUM(erunum) && ISHCUNUM(eeunum)) { nojnumstrip = 1; erlen = strlen(erunum); eelen = strlen(eeunum); } else { return (fmd_fmri_set_errno(EINVAL)); } } if (!nojnumstrip) { erlen = unum_strip_one_jnum(erunum, &erlen) ? erlen : strlen(erunum); eelen = unum_strip_one_jnum(eeunum, &eelen) ? eelen : strlen(eeunum); } return (strncmp(erunum, eeunum, MIN(erlen, eelen)) == 0); }
ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { int err; uint8_t version; uint32_t cpuid; uint64_t serint; char *serstr; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0) return (fmd_fmri_set_errno(EINVAL)); if (version == CPU_SCHEME_VERSION0) { if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0 || nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, &serint) != 0) return (fmd_fmri_set_errno(EINVAL)); return (snprintf(buf, buflen, "cpu:///%s=%u/%s=%llX", FM_FMRI_CPU_ID, cpuid, FM_FMRI_CPU_SERIAL_ID, (u_longlong_t)serint)); } else if (version == CPU_SCHEME_VERSION1) { if (nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) return (fmd_fmri_set_errno(EINVAL)); /* * Serial number is an optional element */ if ((err = nvlist_lookup_string(nvl, FM_FMRI_CPU_SERIAL_ID, &serstr)) != 0) if (err == ENOENT) return (snprintf(buf, buflen, "cpu:///%s=%u", FM_FMRI_CPU_ID, cpuid)); else return (fmd_fmri_set_errno(EINVAL)); else return (snprintf(buf, buflen, "cpu:///%s=%u/%s=%s", FM_FMRI_CPU_ID, cpuid, FM_FMRI_CPU_SERIAL_ID, serstr)); } else { return (fmd_fmri_set_errno(EINVAL)); } }
int fmd_fmri_expand(nvlist_t *nvl) { uint8_t version; uint32_t cpuid; uint64_t serialid; char *serstr, serbuf[21]; /* sizeof (UINT64_MAX) + '\0' */ int rc, err; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || nvlist_lookup_uint32(nvl, FM_FMRI_CPU_ID, &cpuid) != 0) return (fmd_fmri_set_errno(EINVAL)); /* * If the cpu-scheme topology exports this method expand(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_expand(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != ETOPO_METHOD_NOTSUP) return (rc); if (version == CPU_SCHEME_VERSION0) { if ((rc = nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, &serialid)) != 0) { if (rc != ENOENT) return (fmd_fmri_set_errno(rc)); if (cpu_get_serialid_V0(cpuid, &serialid) != 0) return (-1); /* errno is set for us */ if ((rc = nvlist_add_uint64(nvl, FM_FMRI_CPU_SERIAL_ID, serialid)) != 0) return (fmd_fmri_set_errno(rc)); } } else if (version == CPU_SCHEME_VERSION1) { if ((rc = nvlist_lookup_string(nvl, FM_FMRI_CPU_SERIAL_ID, &serstr)) != 0) { if (rc != ENOENT) return (fmd_fmri_set_errno(rc)); if (cpu_get_serialid_V1(cpuid, serbuf, 21) != 0) return (0); /* Serial number is optional */ if ((rc = nvlist_add_string(nvl, FM_FMRI_CPU_SERIAL_ID, serbuf)) != 0) return (fmd_fmri_set_errno(rc)); } } else { return (fmd_fmri_set_errno(EINVAL)); } return (0); }
int fmd_fmri_unusable(nvlist_t *nvl) { uint8_t version; int err, unusable; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_DEV_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); err = 0; unusable = topo_fmri_unusable(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != 0) return (0); else return (unusable); }
int fmd_fmri_service_state(nvlist_t *nvl) { uint8_t version; int err, service_state; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_DEV_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); err = 0; service_state = topo_fmri_service_state(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != 0) return (FMD_SERVICE_STATE_UNKNOWN); else return (service_state); }
int fmd_fmri_replaced(nvlist_t *nvl) { int err, replaced; topo_hdl_t *thp; nvlist_t **hcprs; char *nm; uint_t hcnprs; err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs); if (err != 0) return (fmd_fmri_set_errno(EINVAL)); err = nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm); if (err != 0) return (fmd_fmri_set_errno(EINVAL)); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); replaced = topo_fmri_replaced(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (replaced); }
int fmd_fmri_replaced(nvlist_t *nvl) { int err, rval; topo_hdl_t *thp; if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); err = 0; rval = topo_fmri_replaced(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (rval); }
int fmd_fmri_present(nvlist_t *nvl) { int err, present; topo_hdl_t *thp; if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); err = 0; present = topo_fmri_present(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (present); }
ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { uint8_t version; ssize_t size; char *c; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_LEGACY_SCHEME_VERSION || nvlist_lookup_string(nvl, FM_FMRI_LEGACY_HC, &c) != 0) return (fmd_fmri_set_errno(EINVAL)); c = fmd_fmri_strescape(c); size = snprintf(buf, buflen, "legacy-hc:///component=%s", c); fmd_fmri_strfree(c); return (size); }
int fmd_fmri_contains(nvlist_t *er, nvlist_t *ee) { nvlist_t **erhcl, **eehcl; uint_t erhclsz, eehclsz; nvlist_t *hcsp; uint64_t eroff, eeoff; if (nvlist_lookup_nvlist_array(er, FM_FMRI_HC_LIST, &erhcl, &erhclsz) != 0 || nvlist_lookup_nvlist_array(ee, FM_FMRI_HC_LIST, &eehcl, &eehclsz) != 0) return (fmd_fmri_set_errno(EINVAL)); /* * Check ee is further down the hc tree than er; er and ee have * the same auth and are on the same fru. */ if (hclist_contains(erhcl, erhclsz, eehcl, eehclsz) == 0 || auth_compare(er, ee) != 0 || fru_compare(er, ee) != 0) return (0); /* * return true if er is parent of ee, or er is not a page */ if (erhclsz < eehclsz || nvlist_lookup_nvlist(er, FM_FMRI_HC_SPECIFIC, &hcsp) != 0 || (nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_OFFSET, &eroff) != 0 && nvlist_lookup_uint64(hcsp, "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, &eroff) != 0)) return (1); /* * special case for page fmri: return true if ee is the same page */ if (nvlist_lookup_nvlist(ee, FM_FMRI_HC_SPECIFIC, &hcsp) == 0 && (nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_OFFSET, &eeoff) == 0 || nvlist_lookup_uint64(hcsp, "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, &eeoff) == 0) && eroff == eeoff) return (1); return (0); }
int fmd_fmri_unusable(nvlist_t *nvl) { int err, unusable; topo_hdl_t *thp; nvlist_t **hcprs; char *nm; uint_t hcnprs; if (nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs) != 0 || nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm) != 0) return (0); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); unusable = topo_fmri_unusable(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (unusable == 1 ? 1 : 0); }
/* * Returns 0 (with dimmsp and ndimmsp set) if the unum could be bursted, -1 * otherwise. */ static int mem_unum_burst_pattern(const char *pat, char ***dimmsp, size_t *ndimmsp) { const bank_dimm_t *bd; char **dimms = NULL, **newdimms; size_t ndimms = 0; const char *c; for (bd = bank_dimm; bd->bd_pat != NULL; bd++) { int replace, start, matched; char dimmname[64]; replace = start = matched = -1; (void) sscanf(pat, bd->bd_pat, &replace, &start, &matched); if (matched == -1) continue; (void) strlcpy(dimmname, pat, sizeof (dimmname)); if (bd->bd_subst != NULL) { (void) strlcpy(dimmname+replace, bd->bd_subst, sizeof (dimmname) - strlen(bd->bd_subst)); replace += strlen(bd->bd_subst); } c = pat + start; while (*c != '\0') { int dimmlen = -1; (void) sscanf(c, bd->bd_reppat, &dimmlen); if (dimmlen == -1) break; while (*c == ' ') { c++; dimmlen--; } if (dimmlen > sizeof (dimmname) - replace) break; (void) strlcpy(dimmname + replace, c, dimmlen + 1); newdimms = fmd_fmri_alloc(sizeof (char *) * (ndimms + 1)); if (ndimms != 0) { bcopy(dimms, newdimms, sizeof (char *) * ndimms); fmd_fmri_free(dimms, sizeof (char *) * ndimms); } newdimms[ndimms++] = fmd_fmri_strdup(dimmname); dimms = newdimms; c += dimmlen; if (*c != ' ' && *c != '\0') break; } if (*c != '\0') break; *dimmsp = dimms; *ndimmsp = ndimms; return (0); } mem_strarray_free(dimms, ndimms); return (fmd_fmri_set_errno(EINVAL)); }