17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5724365f7Ssethg * Common Development and Distribution License (the "License"). 6724365f7Ssethg * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*35f59e50SStephen Hanson * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate */ 247c478bd9Sstevel@tonic-gate 250eb822a1Scindi #include <strings.h> 267c478bd9Sstevel@tonic-gate #include <fm/fmd_fmri.h> 27724365f7Ssethg #include <fm/libtopo.h> 280eb822a1Scindi #include <fm/topo_mod.h> 29724365f7Ssethg 30724365f7Ssethg int 31724365f7Ssethg fmd_fmri_init(void) 32724365f7Ssethg { 33724365f7Ssethg return (0); 34724365f7Ssethg } 35724365f7Ssethg 36724365f7Ssethg void 37724365f7Ssethg fmd_fmri_fini(void) 38724365f7Ssethg { 39724365f7Ssethg } 40724365f7Ssethg 410eb822a1Scindi ssize_t 420eb822a1Scindi fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) 43724365f7Ssethg { 44724365f7Ssethg int err; 450eb822a1Scindi uint8_t version; 460eb822a1Scindi ssize_t len; 470eb822a1Scindi topo_hdl_t *thp; 480eb822a1Scindi char *str; 49724365f7Ssethg 500eb822a1Scindi if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 510eb822a1Scindi version > FM_HC_SCHEME_VERSION) 520eb822a1Scindi return (fmd_fmri_set_errno(EINVAL)); 53724365f7Ssethg 5424db4641Seschrock if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 550eb822a1Scindi return (fmd_fmri_set_errno(EINVAL)); 5624db4641Seschrock if (topo_fmri_nvl2str(thp, nvl, &str, &err) != 0) { 5724db4641Seschrock fmd_fmri_topo_rele(thp); 5824db4641Seschrock return (fmd_fmri_set_errno(EINVAL)); 5924db4641Seschrock } 60724365f7Ssethg 610eb822a1Scindi if (buf != NULL) 620eb822a1Scindi len = snprintf(buf, buflen, "%s", str); 630eb822a1Scindi else 640eb822a1Scindi len = strlen(str); 650eb822a1Scindi 660eb822a1Scindi topo_hdl_strfree(thp, str); 6724db4641Seschrock fmd_fmri_topo_rele(thp); 680eb822a1Scindi 690eb822a1Scindi return (len); 70724365f7Ssethg } 71724365f7Ssethg 720eb822a1Scindi int 730eb822a1Scindi fmd_fmri_present(nvlist_t *nvl) 740eb822a1Scindi { 750eb822a1Scindi int err, present; 760eb822a1Scindi topo_hdl_t *thp; 770eb822a1Scindi nvlist_t **hcprs; 780eb822a1Scindi char *nm; 790eb822a1Scindi uint_t hcnprs; 800eb822a1Scindi 810eb822a1Scindi err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs); 82*35f59e50SStephen Hanson if (err != 0) 83*35f59e50SStephen Hanson return (fmd_fmri_set_errno(EINVAL)); 84*35f59e50SStephen Hanson err = nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm); 850eb822a1Scindi if (err != 0) 8625c6ff4bSstephh return (fmd_fmri_set_errno(EINVAL)); 870eb822a1Scindi 8824db4641Seschrock if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 8924db4641Seschrock return (fmd_fmri_set_errno(EINVAL)); 900eb822a1Scindi present = topo_fmri_present(thp, nvl, &err); 9124db4641Seschrock fmd_fmri_topo_rele(thp); 920eb822a1Scindi 930eb822a1Scindi return (present); 9425c6ff4bSstephh } 9525c6ff4bSstephh 9625c6ff4bSstephh int 9725c6ff4bSstephh fmd_fmri_replaced(nvlist_t *nvl) 9825c6ff4bSstephh { 9925c6ff4bSstephh int err, replaced; 10025c6ff4bSstephh topo_hdl_t *thp; 10125c6ff4bSstephh nvlist_t **hcprs; 10225c6ff4bSstephh char *nm; 10325c6ff4bSstephh uint_t hcnprs; 10425c6ff4bSstephh 10525c6ff4bSstephh err = nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, &hcprs, &hcnprs); 106*35f59e50SStephen Hanson if (err != 0) 107*35f59e50SStephen Hanson return (fmd_fmri_set_errno(EINVAL)); 108*35f59e50SStephen Hanson err = nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm); 10925c6ff4bSstephh if (err != 0) 11025c6ff4bSstephh return (fmd_fmri_set_errno(EINVAL)); 11125c6ff4bSstephh 11225c6ff4bSstephh if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 11325c6ff4bSstephh return (fmd_fmri_set_errno(EINVAL)); 11425c6ff4bSstephh replaced = topo_fmri_replaced(thp, nvl, &err); 11525c6ff4bSstephh fmd_fmri_topo_rele(thp); 11625c6ff4bSstephh 11725c6ff4bSstephh return (replaced); 1180eb822a1Scindi } 1190eb822a1Scindi 1207c478bd9Sstevel@tonic-gate int 1217c478bd9Sstevel@tonic-gate fmd_fmri_unusable(nvlist_t *nvl) 1227c478bd9Sstevel@tonic-gate { 123e4b86885SCheng Sean Ye int err, unusable; 124e4b86885SCheng Sean Ye topo_hdl_t *thp; 125e4b86885SCheng Sean Ye nvlist_t **hcprs; 126e4b86885SCheng Sean Ye char *nm; 127e4b86885SCheng Sean Ye uint_t hcnprs; 128e4b86885SCheng Sean Ye 129e4b86885SCheng Sean Ye if (nvlist_lookup_nvlist_array(nvl, FM_FMRI_HC_LIST, 130e4b86885SCheng Sean Ye &hcprs, &hcnprs) != 0 || 131e4b86885SCheng Sean Ye nvlist_lookup_string(hcprs[0], FM_FMRI_HC_NAME, &nm) != 0) 1327c478bd9Sstevel@tonic-gate return (0); 133e4b86885SCheng Sean Ye 134e4b86885SCheng Sean Ye if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 135e4b86885SCheng Sean Ye return (fmd_fmri_set_errno(EINVAL)); 136e4b86885SCheng Sean Ye unusable = topo_fmri_unusable(thp, nvl, &err); 137e4b86885SCheng Sean Ye fmd_fmri_topo_rele(thp); 138e4b86885SCheng Sean Ye 139e4b86885SCheng Sean Ye return (unusable == 1 ? 1 : 0); 140e4b86885SCheng Sean Ye } 141e4b86885SCheng Sean Ye 142e4b86885SCheng Sean Ye static int 143e4b86885SCheng Sean Ye auth_compare(nvlist_t *nvl1, nvlist_t *nvl2) 144e4b86885SCheng Sean Ye { 145e4b86885SCheng Sean Ye const char *names[] = { 146e4b86885SCheng Sean Ye FM_FMRI_AUTH_PRODUCT, 1479c94f155SCheng Sean Ye FM_FMRI_AUTH_PRODUCT_SN, 148e4b86885SCheng Sean Ye FM_FMRI_AUTH_CHASSIS, 149e4b86885SCheng Sean Ye FM_FMRI_AUTH_SERVER, 150e4b86885SCheng Sean Ye FM_FMRI_AUTH_DOMAIN, 151e4b86885SCheng Sean Ye FM_FMRI_AUTH_HOST, 152e4b86885SCheng Sean Ye NULL 153e4b86885SCheng Sean Ye }; 154e4b86885SCheng Sean Ye const char **namep; 155e4b86885SCheng Sean Ye nvlist_t *auth1 = NULL, *auth2 = NULL; 156e4b86885SCheng Sean Ye 157e4b86885SCheng Sean Ye (void) nvlist_lookup_nvlist(nvl1, FM_FMRI_AUTHORITY, &auth1); 158e4b86885SCheng Sean Ye (void) nvlist_lookup_nvlist(nvl2, FM_FMRI_AUTHORITY, &auth2); 159e4b86885SCheng Sean Ye if (auth1 == NULL && auth2 == NULL) 160e4b86885SCheng Sean Ye return (0); 161e4b86885SCheng Sean Ye if (auth1 == NULL || auth2 == NULL) 162e4b86885SCheng Sean Ye return (1); 163e4b86885SCheng Sean Ye 164e4b86885SCheng Sean Ye for (namep = names; *namep != NULL; namep++) { 165e4b86885SCheng Sean Ye char *val1 = NULL, *val2 = NULL; 166e4b86885SCheng Sean Ye 167e4b86885SCheng Sean Ye (void) nvlist_lookup_string(auth1, *namep, &val1); 168e4b86885SCheng Sean Ye (void) nvlist_lookup_string(auth2, *namep, &val2); 169e4b86885SCheng Sean Ye if (val1 == NULL && val2 == NULL) 170e4b86885SCheng Sean Ye continue; 171e4b86885SCheng Sean Ye if (val1 == NULL || val2 == NULL || strcmp(val1, val2) != 0) 172e4b86885SCheng Sean Ye return (1); 173e4b86885SCheng Sean Ye } 174e4b86885SCheng Sean Ye 175e4b86885SCheng Sean Ye return (0); 176e4b86885SCheng Sean Ye } 177e4b86885SCheng Sean Ye 178e4b86885SCheng Sean Ye static int 179e4b86885SCheng Sean Ye hclist_contains(nvlist_t **erhcl, uint_t erhclsz, nvlist_t **eehcl, 180e4b86885SCheng Sean Ye uint_t eehclsz) 181e4b86885SCheng Sean Ye { 182e4b86885SCheng Sean Ye uint_t i; 183e4b86885SCheng Sean Ye char *erval, *eeval; 184e4b86885SCheng Sean Ye 185e4b86885SCheng Sean Ye if (erhclsz > eehclsz || erhcl == NULL || eehcl == NULL) 186e4b86885SCheng Sean Ye return (0); 187e4b86885SCheng Sean Ye 188e4b86885SCheng Sean Ye for (i = 0; i < erhclsz; i++) { 189e4b86885SCheng Sean Ye (void) nvlist_lookup_string(erhcl[i], FM_FMRI_HC_NAME, 190e4b86885SCheng Sean Ye &erval); 191e4b86885SCheng Sean Ye (void) nvlist_lookup_string(eehcl[i], FM_FMRI_HC_NAME, 192e4b86885SCheng Sean Ye &eeval); 193e4b86885SCheng Sean Ye if (strcmp(erval, eeval) != 0) 194e4b86885SCheng Sean Ye return (0); 195e4b86885SCheng Sean Ye (void) nvlist_lookup_string(erhcl[i], FM_FMRI_HC_ID, 196e4b86885SCheng Sean Ye &erval); 197e4b86885SCheng Sean Ye (void) nvlist_lookup_string(eehcl[i], FM_FMRI_HC_ID, 198e4b86885SCheng Sean Ye &eeval); 199e4b86885SCheng Sean Ye if (strcmp(erval, eeval) != 0) 200e4b86885SCheng Sean Ye return (0); 201e4b86885SCheng Sean Ye } 202e4b86885SCheng Sean Ye 203e4b86885SCheng Sean Ye return (1); 204e4b86885SCheng Sean Ye } 205e4b86885SCheng Sean Ye 206e4b86885SCheng Sean Ye static int 207e4b86885SCheng Sean Ye fru_compare(nvlist_t *r1, nvlist_t *r2) 208e4b86885SCheng Sean Ye { 209e4b86885SCheng Sean Ye topo_hdl_t *thp; 210e4b86885SCheng Sean Ye nvlist_t *f1 = NULL, *f2 = NULL; 211e4b86885SCheng Sean Ye nvlist_t **h1 = NULL, **h2 = NULL; 212e4b86885SCheng Sean Ye uint_t h1sz, h2sz; 213e4b86885SCheng Sean Ye int err, rc = 1; 214e4b86885SCheng Sean Ye 215e4b86885SCheng Sean Ye if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 216e4b86885SCheng Sean Ye return (fmd_fmri_set_errno(EINVAL)); 217e4b86885SCheng Sean Ye 218e4b86885SCheng Sean Ye (void) topo_fmri_fru(thp, r1, &f1, &err); 219e4b86885SCheng Sean Ye (void) topo_fmri_fru(thp, r2, &f2, &err); 220e4b86885SCheng Sean Ye if (f1 != NULL && f2 != NULL) { 221e4b86885SCheng Sean Ye (void) nvlist_lookup_nvlist_array(f1, FM_FMRI_HC_LIST, &h1, 222e4b86885SCheng Sean Ye &h1sz); 223e4b86885SCheng Sean Ye (void) nvlist_lookup_nvlist_array(f2, FM_FMRI_HC_LIST, &h2, 224e4b86885SCheng Sean Ye &h2sz); 225e4b86885SCheng Sean Ye if (h1sz == h2sz && hclist_contains(h1, h1sz, h2, h2sz) == 1) 226e4b86885SCheng Sean Ye rc = 0; 227e4b86885SCheng Sean Ye } 228e4b86885SCheng Sean Ye 229e4b86885SCheng Sean Ye fmd_fmri_topo_rele(thp); 230e4b86885SCheng Sean Ye nvlist_free(f1); 231e4b86885SCheng Sean Ye nvlist_free(f2); 232e4b86885SCheng Sean Ye return (rc); 233e4b86885SCheng Sean Ye } 234e4b86885SCheng Sean Ye 235e4b86885SCheng Sean Ye int 236e4b86885SCheng Sean Ye fmd_fmri_contains(nvlist_t *er, nvlist_t *ee) 237e4b86885SCheng Sean Ye { 238e4b86885SCheng Sean Ye nvlist_t **erhcl, **eehcl; 239e4b86885SCheng Sean Ye uint_t erhclsz, eehclsz; 240e4b86885SCheng Sean Ye nvlist_t *hcsp; 241e4b86885SCheng Sean Ye uint64_t eroff, eeoff; 242e4b86885SCheng Sean Ye 243e4b86885SCheng Sean Ye if (nvlist_lookup_nvlist_array(er, FM_FMRI_HC_LIST, &erhcl, 244e4b86885SCheng Sean Ye &erhclsz) != 0 || nvlist_lookup_nvlist_array(ee, 245e4b86885SCheng Sean Ye FM_FMRI_HC_LIST, &eehcl, &eehclsz) != 0) 246e4b86885SCheng Sean Ye return (fmd_fmri_set_errno(EINVAL)); 247e4b86885SCheng Sean Ye 248e4b86885SCheng Sean Ye /* 249e4b86885SCheng Sean Ye * Check ee is further down the hc tree than er; er and ee have 250e4b86885SCheng Sean Ye * the same auth and are on the same fru. 251e4b86885SCheng Sean Ye */ 252e4b86885SCheng Sean Ye if (hclist_contains(erhcl, erhclsz, eehcl, eehclsz) == 0 || 253e4b86885SCheng Sean Ye auth_compare(er, ee) != 0 || fru_compare(er, ee) != 0) 254e4b86885SCheng Sean Ye return (0); 255e4b86885SCheng Sean Ye 256e4b86885SCheng Sean Ye /* 257e4b86885SCheng Sean Ye * return true if er is parent of ee, or er is not a page 258e4b86885SCheng Sean Ye */ 259e4b86885SCheng Sean Ye if (erhclsz < eehclsz || nvlist_lookup_nvlist(er, 260e4b86885SCheng Sean Ye FM_FMRI_HC_SPECIFIC, &hcsp) != 0 || (nvlist_lookup_uint64(hcsp, 261e4b86885SCheng Sean Ye FM_FMRI_HC_SPECIFIC_OFFSET, &eroff) != 0 && 262e4b86885SCheng Sean Ye nvlist_lookup_uint64(hcsp, "asru-" FM_FMRI_HC_SPECIFIC_OFFSET, 263e4b86885SCheng Sean Ye &eroff) != 0)) 264e4b86885SCheng Sean Ye return (1); 265e4b86885SCheng Sean Ye 266e4b86885SCheng Sean Ye /* 267e4b86885SCheng Sean Ye * special case for page fmri: return true if ee is the same page 268e4b86885SCheng Sean Ye */ 269e4b86885SCheng Sean Ye if (nvlist_lookup_nvlist(ee, FM_FMRI_HC_SPECIFIC, &hcsp) == 0 && 270e4b86885SCheng Sean Ye (nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_OFFSET, 271e4b86885SCheng Sean Ye &eeoff) == 0 || nvlist_lookup_uint64(hcsp, "asru-" 272e4b86885SCheng Sean Ye FM_FMRI_HC_SPECIFIC_OFFSET, &eeoff) == 0) && eroff == eeoff) 273e4b86885SCheng Sean Ye return (1); 274e4b86885SCheng Sean Ye 275e4b86885SCheng Sean Ye return (0); 276e4b86885SCheng Sean Ye } 277e4b86885SCheng Sean Ye 278e4b86885SCheng Sean Ye int 279e4b86885SCheng Sean Ye fmd_fmri_service_state(nvlist_t *nvl) 280e4b86885SCheng Sean Ye { 281e4b86885SCheng Sean Ye uint8_t version; 282e4b86885SCheng Sean Ye int err, service_state; 283e4b86885SCheng Sean Ye topo_hdl_t *thp; 284e4b86885SCheng Sean Ye 285e4b86885SCheng Sean Ye if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || 286e4b86885SCheng Sean Ye version > FM_DEV_SCHEME_VERSION) 287e4b86885SCheng Sean Ye return (fmd_fmri_set_errno(EINVAL)); 288e4b86885SCheng Sean Ye 289e4b86885SCheng Sean Ye if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) 290e4b86885SCheng Sean Ye return (fmd_fmri_set_errno(EINVAL)); 291e4b86885SCheng Sean Ye err = 0; 292e4b86885SCheng Sean Ye service_state = topo_fmri_service_state(thp, nvl, &err); 293e4b86885SCheng Sean Ye fmd_fmri_topo_rele(thp); 294e4b86885SCheng Sean Ye 295e4b86885SCheng Sean Ye if (err != 0) 296e4b86885SCheng Sean Ye return (FMD_SERVICE_STATE_UNKNOWN); 297e4b86885SCheng Sean Ye else 298e4b86885SCheng Sean Ye return (service_state); 2997c478bd9Sstevel@tonic-gate } 300