# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. # SUBDIRS = \ cpu \ dev \ fmd \ hc \ legacy-hc \ mem \ mod \ pcie \ pkg \ sw \ svc \ zfs include ../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # .KEEP_STATE: .SUFFIXES: include ../../../../Makefile.cmd SCHEME = $(shell cd ..; basename `pwd`) # # For now, we assume a scheme is named after its directory and its source file # is named 'scheme.c'. If schemes get more complicated this can be enhanced # to derive the values from the lower-level Makefiles. # PROG = $(SCHEME:%=%.so) SRCS = scheme.c OBJS = $(SRCS:%.c=%.o) ROOTPROG = $(ROOT)/usr/lib/fm/fmd/schemes/$(PROG) ROOTPROG64 = $(ROOT)/usr/lib/fm/fmd/schemes/$(MACH64)/$(PROG) MAPFILE = ../../../fmd/common/fmd_fmri.map CFLAGS += $(CTF_FLAGS) $(CCVERBOSE) $(CC_PICFLAGS) CFLAGS += $(GSHARED) CFLAGS64 += $(CTF_FLAGS) $(CCVERBOSE) $(CC_PICFLAGS) CFLAGS64 += $(GSHARED) CPPFLAGS += -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT -D$(MACH) -I.. # Hammerhead: FMD schemes are dlopen'd at runtime - disable strict symbol checking ZDEFS = LDFLAGS += $(ZTEXT) $(ZDEFS) $(ZIGNORE) -Wl,-M$(MAPFILE) LDLIBS += -lnvpair -lc # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # all: $(PROG) .NOTPARALLEL: .PARALLEL: $(OBJS) $(PROG): $(OBJS) $(MAPFILE) $(LINK.c) $(OBJS) -o $@ $(LDLIBS) $(CTFMERGE) -L VERSION -o $@ $(OBJS) $(POST_PROCESS_SO) %.o: %.c $(COMPILE.c) $< $(CTFCONVERT_O) %.o: ../$(MACH)/%.c $(COMPILE.c) $< $(CTFCONVERT_O) %.o: ../%.c $(COMPILE.c) $< $(CTFCONVERT_O) %.o: ../../common/%.c $(COMPILE.c) $< $(CTFCONVERT_O) clean: $(RM) $(OBJS) clobber: clean $(RM) $(PROG) install_h: $(ROOT)/usr/lib/fm: $(INS.dir) $(ROOT)/usr/lib/fm/fmd: $(ROOT)/usr/lib/fm $(INS.dir) $(ROOT)/usr/lib/fm/fmd/schemes: $(ROOT)/usr/lib/fm/fmd $(INS.dir) $(ROOT)/usr/lib/fm/fmd/schemes/$(MACH64): $(ROOT)/usr/lib/fm/fmd/schemes $(INS.dir) # Hammerhead: .SECONDEXPANSION required for $$(@D) to resolve target directory .SECONDEXPANSION: $(ROOTPROG): $$(@D) $(PROG) $(RM) $@; $(INS) -s -m 0555 -f $(@D) $(PROG) $(ROOTPROG64): $$(@D) $(PROG) $(RM) $@; $(INS) -s -m 0555 -f $(@D) $(PROG) # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../../Makefile.com include $(SRC)/Makefile.master.64 SRCS = cpu.c # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -lkstat \ -L$(ROOTLIB)/fm -ltopo LDFLAGS += -R/usr/lib/fm CERRWARN += -Wno-parentheses include ../../Makefile.targ install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include /* * The scheme plugin for cpu FMRIs. */ 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); } /* * Determine if a cpuid is present. */ /*ARGSUSED*/ static int cpu_cpuid_present(uint32_t cpuid) { #ifdef sparc /* * For SPARC, use kstats to see if the cpuid is present. * Note that this may need to change for sun4v. */ kstat_ctl_t *kc; kstat_t *ksp = NULL; if ((kc = kstat_open()) == NULL) return (-1); /* errno is set for us */ ksp = kstat_lookup(kc, "cpu_info", cpuid, NULL); (void) kstat_close(kc); return ((ksp == NULL) ? 0 : 1); #else /* sparc */ /* * For x64, just return true. */ return (1); #endif /* sparc */ } 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)); } static int cpu_get_serialid_V1(uint32_t cpuid, char *serbuf, size_t len) { int err; uint64_t serial = 0; err = cpu_get_serialid_kstat(cpuid, &serial); (void) snprintf(serbuf, len, "%llX", (u_longlong_t)serial); return (err); } static int cpu_get_serialid_V0(uint32_t cpuid, uint64_t *serialidp) { return (cpu_get_serialid_kstat(cpuid, serialidp)); } 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_present(nvlist_t *nvl) { int rc, err; 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 present(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_present(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 ? 0 : -1); return (curserid == nvlserid); } 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) return (cpu_cpuid_present(cpuid)); return (strcmp(curserbuf, nvlserstr) == 0 ? 1 : 0); } else { return (fmd_fmri_set_errno(EINVAL)); } } 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)); } } 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); } int fmd_fmri_contains(nvlist_t *er, nvlist_t *ee) { int ret1, ret2; char *erserstr, *eeserstr; uint8_t erversion, eeversion; uint64_t erserint, eeserint; uint32_t erval, eeval; if (nvlist_lookup_uint32(er, FM_FMRI_CPU_ID, &erval) != 0) return (0); if (nvlist_lookup_uint32(ee, FM_FMRI_CPU_ID, &eeval) != 0) return (0); if (erval != eeval) return (0); if (nvlist_lookup_uint8(er, FM_VERSION, &erversion) != 0) return (0); if (nvlist_lookup_uint8(ee, FM_VERSION, &eeversion) != 0) return (0); if (erversion != eeversion) return (0); if (erversion == CPU_SCHEME_VERSION0) { if (nvlist_lookup_uint64(er, FM_FMRI_CPU_SERIAL_ID, &erserint) != 0) return (0); if (nvlist_lookup_uint64(ee, FM_FMRI_CPU_SERIAL_ID, &eeserint) != 0) return (0); if (erserint != eeserint) return (0); } else if (erversion == CPU_SCHEME_VERSION1) { /* Serial ID is an optional element */ ret1 = nvlist_lookup_string(er, FM_FMRI_CPU_SERIAL_ID, &erserstr); ret2 = nvlist_lookup_string(ee, FM_FMRI_CPU_SERIAL_ID, &eeserstr); if (ret1 != ret2) return (0); if (ret1 == ENOENT) /* * Serial IDs not found in both container, containee */ return (1); if (ret1 != 0) return (0); /* * Found Serial Ids in both container and containee. * Check if they are same. */ if (strlen(erserstr) != strlen(eeserstr)) return (0); if (strcmp(erserstr, eeserstr) != 0) return (0); } return (1); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com LDLIBS += -ldevinfo # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -ltopo # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm LINTFLAGS += -L$(ROOT)/usr/lib/fm install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include int fmd_fmri_init(void) { return (0); } void fmd_fmri_fini(void) { } 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_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); } 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_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); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) LDLIBS += -lc include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include /* * This routine should be kept in sync with the built-in version provided * as part of fmd(8) itself -- see usr/src/cmd/fm/fmd/common/fmd_scheme.c */ ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { char *name; if (nvlist_lookup_string(nvl, FM_FMRI_FMD_NAME, &name) != 0) return (fmd_fmri_set_errno(EINVAL)); return (snprintf(buf, buflen, "%s:///module/%s", FM_FMRI_SCHEME_FMD, name)); } /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /*ARGSUSED*/ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /*ARGSUSED*/ int fmd_fmri_unusable(nvlist_t *nvl) { return (0); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -ltopo # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm LINTFLAGS += -L$(ROOT)/usr/lib/fm install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include int fmd_fmri_init(void) { return (0); } void fmd_fmri_fini(void) { } ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { int err; uint8_t version; ssize_t len; topo_hdl_t *thp; char *str; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_HC_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); 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_present(nvlist_t *nvl) { int err, present; 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)); present = topo_fmri_present(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (present); } 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_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); } static int auth_compare(nvlist_t *nvl1, nvlist_t *nvl2) { const char *names[] = { FM_FMRI_AUTH_PRODUCT, FM_FMRI_AUTH_PRODUCT_SN, FM_FMRI_AUTH_CHASSIS, FM_FMRI_AUTH_SERVER, FM_FMRI_AUTH_DOMAIN, FM_FMRI_AUTH_HOST, NULL }; const char **namep; nvlist_t *auth1 = NULL, *auth2 = NULL; (void) nvlist_lookup_nvlist(nvl1, FM_FMRI_AUTHORITY, &auth1); (void) nvlist_lookup_nvlist(nvl2, FM_FMRI_AUTHORITY, &auth2); if (auth1 == NULL && auth2 == NULL) return (0); if (auth1 == NULL || auth2 == NULL) return (1); for (namep = names; *namep != NULL; namep++) { char *val1 = NULL, *val2 = NULL; (void) nvlist_lookup_string(auth1, *namep, &val1); (void) nvlist_lookup_string(auth2, *namep, &val2); if (val1 == NULL && val2 == NULL) continue; if (val1 == NULL || val2 == NULL || strcmp(val1, val2) != 0) return (1); } return (0); } static int hclist_contains(nvlist_t **erhcl, uint_t erhclsz, nvlist_t **eehcl, uint_t eehclsz) { uint_t i; char *erval, *eeval; if (erhclsz > eehclsz || erhcl == NULL || eehcl == NULL) return (0); for (i = 0; i < erhclsz; i++) { (void) nvlist_lookup_string(erhcl[i], FM_FMRI_HC_NAME, &erval); (void) nvlist_lookup_string(eehcl[i], FM_FMRI_HC_NAME, &eeval); if (strcmp(erval, eeval) != 0) return (0); (void) nvlist_lookup_string(erhcl[i], FM_FMRI_HC_ID, &erval); (void) nvlist_lookup_string(eehcl[i], FM_FMRI_HC_ID, &eeval); if (strcmp(erval, eeval) != 0) return (0); } return (1); } 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); nvlist_free(f1); nvlist_free(f2); return (rc); } 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_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); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include 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); } /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /*ARGSUSED*/ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /*ARGSUSED*/ int fmd_fmri_unusable(nvlist_t *nvl) { return (0); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com SRCS = \ mem.c \ mem_read.c \ mem_unum.c \ mem_util.c # Hammerhead: mem_disc.c removed - was in intel/ ISA subdir, not in tree # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ # Hammerhead: 64-bit only - flatten FM library paths LDLIBS += -L$(ROOTLIB)/fm -lfmd_agent -ltopo LDFLAGS += -R/usr/lib/fm install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include mem_t mem; static int mem_fmri_get_unum(nvlist_t *nvl, char **unump) { uint8_t version; char *unum; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_MEM_SCHEME_VERSION || nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unum) != 0) return (fmd_fmri_set_errno(EINVAL)); *unump = unum; return (0); } static int page_isretired(nvlist_t *fmri, int *errp) { fmd_agent_hdl_t *hdl; int rc, err; if ((hdl = fmd_agent_open(FMD_AGENT_VERSION)) == NULL) return (-1); rc = fmd_agent_page_isretired(hdl, fmri); err = fmd_agent_errno(hdl); fmd_agent_close(hdl); if (errp != NULL) *errp = err; return (rc); } ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { char format[64]; ssize_t size, presz; char *rawunum, *preunum, *escunum, *prefix; uint64_t val; int i; if (mem_fmri_get_unum(nvl, &rawunum) < 0) return (-1); /* errno is set for us */ /* * If we have a well-formed unum (hc-FMRI), use the string verbatim * to form the initial mem:/// components. Otherwise use unum=%s. */ if (strncmp(rawunum, "hc://", 5) != 0) prefix = FM_FMRI_MEM_UNUM "="; else prefix = ""; /* * If we have a DIMM offset, include it in the string. If we have a PA * then use that. Otherwise just format the unum element. */ if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val) == 0) { (void) snprintf(format, sizeof (format), "%s:///%s%%1$s/%s=%%2$llx", FM_FMRI_SCHEME_MEM, prefix, FM_FMRI_MEM_OFFSET); } else if (nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val) == 0) { (void) snprintf(format, sizeof (format), "%s:///%s%%1$s/%s=%%2$llx", FM_FMRI_SCHEME_MEM, prefix, FM_FMRI_MEM_PHYSADDR); } else { (void) snprintf(format, sizeof (format), "%s:///%s%%1$s", FM_FMRI_SCHEME_MEM, prefix); } /* * If we have a well-formed unum (hc-FMRI), we skip over the * the scheme and authority prefix. * Otherwise, the spaces and colons will be escaped, * rendering the resulting FMRI pretty much unreadable. * We're therefore going to do some escaping of our own first. */ if (strncmp(rawunum, "hc://", 5) == 0) { rawunum += 5; rawunum = strchr(rawunum, '/'); ++rawunum; /* LINTED: variable format specifier */ size = snprintf(buf, buflen, format, rawunum, val); } else { preunum = fmd_fmri_strdup(rawunum); presz = strlen(preunum) + 1; for (i = 0; i < presz - 1; i++) { if (preunum[i] == ':' && preunum[i + 1] == ' ') { bcopy(preunum + i + 2, preunum + i + 1, presz - (i + 2)); } else if (preunum[i] == ' ') { preunum[i] = ','; } } escunum = fmd_fmri_strescape(preunum); fmd_fmri_free(preunum, presz); /* LINTED: variable format specifier */ size = snprintf(buf, buflen, format, escunum, val); fmd_fmri_strfree(escunum); } return (size); } int fmd_fmri_expand(nvlist_t *nvl) { char *unum, **serids; uint_t nnvlserids; size_t nserids; int rc, err = 0; topo_hdl_t *thp; if ((mem_fmri_get_unum(nvl, &unum) < 0) || (*unum == '\0')) return (fmd_fmri_set_errno(EINVAL)); /* * If the mem-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 ((rc = nvlist_lookup_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, &serids, &nnvlserids)) == 0) { /* already have serial #s */ return (0); } else if (rc != ENOENT) return (fmd_fmri_set_errno(EINVAL)); if (mem_get_serids_by_unum(unum, &serids, &nserids) < 0) { /* errno is set for us */ if (errno == ENOTSUP) return (0); /* nothing to add - no s/n support */ else return (-1); } rc = nvlist_add_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, serids, nserids); mem_strarray_free(serids, nserids); if (rc != 0) return (fmd_fmri_set_errno(EINVAL)); else return (0); } #ifdef sparc static int serids_eq(char **serids1, uint_t nserids1, char **serids2, uint_t nserids2) { int i; if (nserids1 != nserids2) return (0); for (i = 0; i < nserids1; i++) { if (strcmp(serids1[i], serids2[i]) != 0) return (0); } return (1); } #endif /* sparc */ int fmd_fmri_present(nvlist_t *nvl) { char *unum = NULL; int rc, err = 0; struct topo_hdl *thp; #ifdef sparc char **nvlserids, **serids; uint_t nnvlserids; size_t nserids; #else nvlist_t *unum_nvl; nvlist_t *nvlcp = NULL; uint64_t val; #endif /* sparc */ if (mem_fmri_get_unum(nvl, &unum) < 0) return (-1); /* errno is set for us */ #ifdef sparc /* * If the mem-scheme topology exports this method present(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_present(thp, nvl, &err); fmd_fmri_topo_rele(thp); if (err != ETOPO_METHOD_NOTSUP) return (rc); if (nvlist_lookup_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, &nvlserids, &nnvlserids) != 0) { /* * Some mem scheme FMRIs don't have serial ids because * either the platform does not support them, or because * the FMRI was created before support for serial ids was * introduced. If this is the case, assume it is there. */ if (mem.mem_dm == NULL) return (1); else return (fmd_fmri_set_errno(EINVAL)); } if (mem_get_serids_by_unum(unum, &serids, &nserids) < 0) { if (errno == ENOTSUP) return (1); /* assume it's there, no s/n support here */ if (errno != ENOENT) { /* * Errors are only signalled to the caller if they're * the caller's fault. This isn't - it's a failure on * our part to burst or read the serial numbers. We'll * whine about it, and tell the caller the named * module(s) isn't/aren't there. */ fmd_fmri_warn("failed to retrieve serial number for " "unum %s", unum); } return (0); } rc = serids_eq(serids, nserids, nvlserids, nnvlserids); mem_strarray_free(serids, nserids); #else /* * On X86 we will invoke the topo is_present method passing in the * unum, which is in hc scheme. The libtopo hc-scheme is_present method * will invoke the node-specific is_present method, which is implemented * by the chip enumerator for rank nodes. The rank node's is_present * method will compare the serial number in the unum with the current * serial to determine if the same DIMM is present. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) { fmd_fmri_warn("failed to get handle to topology"); return (-1); } if (topo_fmri_str2nvl(thp, unum, &unum_nvl, &err) == 0) { rc = topo_fmri_present(thp, unum_nvl, &err); nvlist_free(unum_nvl); } else rc = fmd_fmri_set_errno(EINVAL); fmd_fmri_topo_rele(thp); /* * Need to check if this is a valid page too. if "isretired" returns * EINVAL, assume page invalid and return not_present. */ if (rc == 1 && nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val) == 0 && nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val) == 0 && mem_unum_rewrite(nvl, &nvlcp) == 0 && nvlcp != NULL) { int page_err, rval = page_isretired(nvlcp, &page_err); if (rval == FMD_AGENT_RETIRE_DONE && page_err == EINVAL) rc = 0; nvlist_free(nvlcp); } #endif /* sparc */ return (rc); } int fmd_fmri_replaced(nvlist_t *nvl) { char *unum = NULL; int rc, err = 0; struct topo_hdl *thp; #ifdef sparc char **nvlserids, **serids; uint_t nnvlserids; size_t nserids; #else nvlist_t *unum_nvl; nvlist_t *nvlcp = NULL; uint64_t val; #endif /* sparc */ if (mem_fmri_get_unum(nvl, &unum) < 0) return (-1); /* errno is set for us */ #ifdef sparc /* * If the mem-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 (nvlist_lookup_string_array(nvl, FM_FMRI_MEM_SERIAL_ID, &nvlserids, &nnvlserids) != 0) { /* * Some mem scheme FMRIs don't have serial ids because * either the platform does not support them, or because * the FMRI was created before support for serial ids was * introduced. If this is the case, assume it is there. */ if (mem.mem_dm == NULL) return (FMD_OBJ_STATE_UNKNOWN); else return (fmd_fmri_set_errno(EINVAL)); } if (mem_get_serids_by_unum(unum, &serids, &nserids) < 0) { if (errno == ENOTSUP) return (FMD_OBJ_STATE_UNKNOWN); if (errno != ENOENT) { /* * Errors are only signalled to the caller if they're * the caller's fault. This isn't - it's a failure on * our part to burst or read the serial numbers. We'll * whine about it, and tell the caller the named * module(s) isn't/aren't there. */ fmd_fmri_warn("failed to retrieve serial number for " "unum %s", unum); } return (FMD_OBJ_STATE_NOT_PRESENT); } rc = serids_eq(serids, nserids, nvlserids, nnvlserids) ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_REPLACED; mem_strarray_free(serids, nserids); #else /* * On X86 we will invoke the topo is_replaced method passing in the * unum, which is in hc scheme. The libtopo hc-scheme is_replaced * method will invoke the node-specific is_replaced method, which is * implemented by the chip enumerator for rank nodes. The rank node's * is_replaced method will compare the serial number in the unum with * the current serial to determine if the same DIMM is replaced. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) { fmd_fmri_warn("failed to get handle to topology"); return (-1); } if (topo_fmri_str2nvl(thp, unum, &unum_nvl, &err) == 0) { rc = topo_fmri_replaced(thp, unum_nvl, &err); nvlist_free(unum_nvl); } else rc = fmd_fmri_set_errno(EINVAL); fmd_fmri_topo_rele(thp); /* * Need to check if this is a valid page too. if "isretired" returns * EINVAL, assume page invalid and return not_present. */ if ((rc == FMD_OBJ_STATE_STILL_PRESENT || rc == FMD_OBJ_STATE_UNKNOWN) && nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val) == 0 && nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val) == 0 && mem_unum_rewrite(nvl, &nvlcp) == 0 && nvlcp != NULL) { int page_err, rval = page_isretired(nvlcp, &page_err); if (rval == FMD_AGENT_RETIRE_DONE && page_err == EINVAL) rc = FMD_OBJ_STATE_NOT_PRESENT; nvlist_free(nvlcp); } #endif /* sparc */ return (rc); } int fmd_fmri_contains(nvlist_t *er, nvlist_t *ee) { int rc, err = 0; struct topo_hdl *thp; char *erunum, *eeunum; uint64_t erval = 0, eeval = 0; /* * If the mem-scheme topology exports this method contains(), invoke it. */ if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); rc = topo_fmri_contains(thp, er, ee, &err); fmd_fmri_topo_rele(thp); if (err != ETOPO_METHOD_NOTSUP) return (rc); if (mem_fmri_get_unum(er, &erunum) < 0 || mem_fmri_get_unum(ee, &eeunum) < 0) return (-1); /* errno is set for us */ if (mem_unum_contains(erunum, eeunum) <= 0) return (0); /* can't parse/match, so assume no containment */ if (nvlist_lookup_uint64(er, FM_FMRI_MEM_OFFSET, &erval) == 0) { return (nvlist_lookup_uint64(ee, FM_FMRI_MEM_OFFSET, &eeval) == 0 && erval == eeval); } if (nvlist_lookup_uint64(er, FM_FMRI_MEM_PHYSADDR, &erval) == 0) { return (nvlist_lookup_uint64(ee, FM_FMRI_MEM_PHYSADDR, &eeval) == 0 && erval == eeval); } return (1); } /* * We can only make a usable/unusable determination for pages. Mem FMRIs * without page addresses will be reported as usable since Solaris has no * way at present to dynamically disable an entire DIMM or DIMM pair. */ int fmd_fmri_unusable(nvlist_t *nvl) { uint64_t val1, val2; uint8_t version; int rc, err1 = 0, err2; nvlist_t *nvlcp = NULL; int retval; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_MEM_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); /* * If the mem-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, &err1); fmd_fmri_topo_rele(thp); if (err1 != ETOPO_METHOD_NOTSUP) return (rc); err1 = nvlist_lookup_uint64(nvl, FM_FMRI_MEM_OFFSET, &val1); err2 = nvlist_lookup_uint64(nvl, FM_FMRI_MEM_PHYSADDR, &val2); if (err1 == ENOENT && err2 == ENOENT) return (0); /* no page, so assume it's still usable */ if ((err1 != 0 && err1 != ENOENT) || (err2 != 0 && err2 != ENOENT)) return (fmd_fmri_set_errno(EINVAL)); if ((rc = mem_unum_rewrite(nvl, &nvlcp)) != 0) return (fmd_fmri_set_errno(rc)); /* * Ask the kernel if the page is retired, using either the rewritten * hc FMRI or the original mem FMRI with the specified offset or PA. * Refer to the kernel's page_retire_check() for the error codes. */ rc = page_isretired(nvlcp ? nvlcp : nvl, NULL); if (rc == FMD_AGENT_RETIRE_FAIL) { /* * The page is not retired and is not scheduled for retirement * (i.e. no request pending and has not seen any errors) */ retval = 0; } else if (rc == FMD_AGENT_RETIRE_DONE || rc == FMD_AGENT_RETIRE_ASYNC) { /* * The page has been retired, is in the process of being * retired, or doesn't exist. The latter is valid if the page * existed in the past but has been DR'd out. */ retval = 1; } else { /* * Errors are only signalled to the caller if they're the * caller's fault. This isn't - it's a failure of the * retirement-check code. We'll whine about it and tell * the caller the page is unusable. */ fmd_fmri_warn("failed to determine page %s=%llx usability: " "rc=%d errno=%d\n", err1 == 0 ? FM_FMRI_MEM_OFFSET : FM_FMRI_MEM_PHYSADDR, err1 == 0 ? (u_longlong_t)val1 : (u_longlong_t)val2, rc, errno); retval = 1; } nvlist_free(nvlcp); return (retval); } int fmd_fmri_init(void) { return (mem_discover()); } void fmd_fmri_fini(void) { mem_dimm_map_t *dm, *em; mem_bank_map_t *bm, *cm; mem_grp_t *gm, *hm; mem_seg_map_t *sm, *tm; for (dm = mem.mem_dm; dm != NULL; dm = em) { em = dm->dm_next; fmd_fmri_strfree(dm->dm_label); fmd_fmri_strfree(dm->dm_part); fmd_fmri_strfree(dm->dm_device); fmd_fmri_free(dm, sizeof (mem_dimm_map_t)); } for (bm = mem.mem_bank; bm != NULL; bm = cm) { cm = bm->bm_next; fmd_fmri_free(bm, sizeof (mem_bank_map_t)); } for (gm = mem.mem_group; gm != NULL; gm = hm) { hm = gm->mg_next; fmd_fmri_free(gm, sizeof (mem_grp_t)); } for (sm = mem.mem_seg; sm != NULL; sm = tm) { tm = sm->sm_next; fmd_fmri_free(sm, sizeof (mem_seg_map_t)); } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MEM_H #define _MEM_H #include #include #ifdef __cplusplus extern "C" { #endif /* * FMRI plugin for the `mem' scheme. * * The mem scheme can be used to name individual memory modules, as well as * groups of memory modules, also known as banks. The name `dimm' is used as a * synonym for individual memory modules, for no good reason. Mem FMRIs can * be further refined with the addition of a member which identifies a * particular physical page within the bank or DIMM. The named page is as * viewed by the VM system, and may thus span multiple memory modules. It will, * however, be at least partially contained by the named bank or DIMM. * * Memory modules are identified by two things - their physical position, or * slot, in the machine, and their serial number. DIMMs are identified by this * tuple on platforms which support the retrieval of serial numbers. Platforms * which don't have this support rely on the slot number, with the corresponding * degradation in their ability to detect hardware changees. * * The physical location is embodied by the unum, which is highly specific to * each platform, and bears a passing resemblance to the name of the slot, as * printed on the actual hardware. The unum is mapped to a DIMM-specific * device, which is then read to determine the serial number. See mem_disc.c * for details of the process by which unums are mapped to devices, and * mem_read.c for the code which actually retrieves the serial number from the * device. * * Banks are also identified by unums, which must be broken apart into the * unums which identify each constituent memory module. Serial numbers are * retrieved for banks - one per member module - in the same way as for * individual modules. See mem_unum.c for the code which bursts bank unums. * * Serial number retrieval, on platforms which support it, is very expensive * (on the order of several tenths of a second, which adds up in a hurry on * larger machines). So, while we pre-generate the list of DIMM device paths, * we only read their serial numbers when requested by plugin consumers. To * further reduce the perceived cost, we don't re-read until/unless we detect * that a DR operation has taken place. * * Using the facilities described above, the plugin implements the following * entry points: (see mem.c) * * - nvl2str: The printed representation of the named bank or DIMM is * generated. No attempt is made to determine whether or not the named * item is still present in the system. * * - expand: For platforms which do not include bank or DIMM * serial numbers in their ereports, this entry point will read the * serial number(s) for the named item, and will add it/them to the passed * FMRI. Errors will be returned if the FMRI (unum) was unparseable, or if * the serial number could not be retrieved. * * - present: Given a mem-schemed FMRI with a serial number, this entry * point will attempt to determine whether the bank or module named in the * FMRI is still present in the system at the same location. Programmer * errors (invalid FMRIs) will be signalled to the caller. Warnings will * be emitted for otherwise-valid FMRIs whose serial numbers could not be * read, with the caller told that the FMRI is not present. * * - contains: Used to determine whether a given bank contains a given DIMM. * No attempt is made to determine whether the module named by the FMRIs are * actually present in the system. Programmer errors (invalidd FMRIs) will * be returned to the caller. Warnings will be emitted for otherwise-valid * FMRIs whose relationship could not be determined, with the caller told * that there is no relationship. */ /* * 18+nul for SPD, 6+nul for SEEPROM, 15+nul max for Serengeti, Starcat, LW8. * 18 for Sun Partnumber, 18 partner partnumber, 12 serialnumber for OPL. */ #define MEM_SERID_MAXLEN 64 #define MAX_DIMMS_PER_BANK 4 typedef struct mem_dimm_map { struct mem_dimm_map *dm_next; /* The next DIMM map */ char *dm_label; /* The UNUM for this DIMM */ char *dm_device; /* Path to I2C device for DIMM */ char dm_serid[MEM_SERID_MAXLEN]; /* Cached serial number */ char *dm_part; /* DIMM part number */ uint64_t dm_drgen; /* DR gen count for cached S/N */ } mem_dimm_map_t; typedef struct mem_bank_map { struct mem_bank_map *bm_next; /* the next bank map overall */ struct mem_bank_map *bm_grp; /* next bank map in group */ uint64_t bm_mask; uint64_t bm_match; uint16_t bm_shift; /* dimms-per-reference shift */ mem_dimm_map_t *bm_dimm[MAX_DIMMS_PER_BANK]; } mem_bank_map_t; typedef struct mem_grp { struct mem_grp *mg_next; size_t mg_size; mem_bank_map_t *mg_bank; } mem_grp_t; typedef struct mem_seg_map { struct mem_seg_map *sm_next; /* the next segment map */ uint64_t sm_base; /* base address for this segment */ uint64_t sm_size; /* size for this segment */ mem_grp_t *sm_grp; } mem_seg_map_t; typedef struct mem { mem_dimm_map_t *mem_dm; /* List supported DIMMs */ uint64_t mem_memconfig; /* HV memory-configuration-id# */ mem_seg_map_t *mem_seg; /* list of defined segments */ mem_bank_map_t *mem_bank; mem_grp_t *mem_group; /* groups of banks for a segment */ } mem_t; extern int mem_discover(void); extern int mem_get_serid(const char *, char *, size_t); extern int mem_get_serids_by_unum(const char *, char ***, size_t *); extern void mem_expand_opt(nvlist_t *, char *, char **); extern int mem_unum_burst(const char *, char ***, size_t *); extern int mem_unum_contains(const char *, const char *); extern int mem_unum_rewrite(nvlist_t *, nvlist_t **); extern void mem_strarray_free(char **, size_t); extern mem_t mem; #ifdef __cplusplus } #endif #endif /* _MEM_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Retrieval of the DIMM serial number from data encoded in the SPD and * SEEPROM formats. */ #include #include #include #include #include #include #include #include #include #include #include #include #define BUFSIZ_SPD 256 #define BUFSIZ_SEEPROM 8192 /* * SEEPROMs are composed of self-describing containers. The first container, * starting at offset 0, is r/w. The second container, starting at 0x1800, is * r/o, and contains identification information supplied by the manufacturer. */ #define SEEPROM_OFFSET_RO 0x1800 static int mem_get_spd_serid(const char *buf, size_t bufsz, char *serid, size_t seridsz) { static const char hex_digits[] = "0123456789ABCDEF"; spd_data_t *spd = (spd_data_t *)buf; char *c; int i; if (bufsz < sizeof (spd_data_t)) return (fmd_fmri_set_errno(EINVAL)); if (seridsz < sizeof (spd->asmb_serial_no) * 2 + 1) return (fmd_fmri_set_errno(EINVAL)); for (c = serid, i = 0; i < sizeof (spd->asmb_serial_no); i++) { *c++ = hex_digits[spd->asmb_serial_no[i] >> 4]; *c++ = hex_digits[spd->asmb_serial_no[i] & 0xf]; } *c = '\0'; return (0); } static void * seeprom_seg_lookup(const char *buf, size_t bufsz, char *segname, size_t *segszp) { seeprom_container_t *sc; seeprom_seg_t *segp, seg; int sidx; if (strlen(segname) != sizeof (seg.sees_name)) return (NULL); sc = (seeprom_container_t *)(buf + SEEPROM_OFFSET_RO); /* Validate sc size then dereference it */ if (bufsz < SEEPROM_OFFSET_RO + sizeof (seeprom_container_t) || bufsz < SEEPROM_OFFSET_RO + sizeof (seeprom_container_t) + sc->seec_contsz) return (NULL); if (sc->seec_tag == 0 || sc->seec_contsz == 0 || sc->seec_nsegs == 0) return (NULL); for (sidx = 0; sidx < sc->seec_nsegs; sidx++) { /* LINTED - pointer alignment */ segp = ((seeprom_seg_t *)(sc + 1)) + sidx; bcopy(segp, &seg, sizeof (seeprom_seg_t)); seg.sees_segoff = ntohs(seg.sees_segoff); seg.sees_seglen = ntohs(seg.sees_seglen); if (bufsz < seg.sees_segoff + seg.sees_seglen) return (NULL); if (strncmp(segname, seg.sees_name, sizeof (seg.sees_name)) == 0) { *segszp = seg.sees_seglen; return ((void *)(buf + seg.sees_segoff)); } } return (NULL); } static int mem_get_seeprom_serid(const char *buf, size_t bufsz, char *serid, size_t seridsz) { seeprom_seg_sd_t *sd; size_t segsz; if (seridsz < sizeof (sd->seesd_sun_sno) + 1) return (fmd_fmri_set_errno(EINVAL)); if ((sd = seeprom_seg_lookup(buf, bufsz, "SD", &segsz)) == NULL) return (fmd_fmri_set_errno(EINVAL)); if (segsz < sizeof (seeprom_seg_sd_t)) return (fmd_fmri_set_errno(EINVAL)); bcopy(sd->seesd_sun_sno, serid, sizeof (sd->seesd_sun_sno)); serid[sizeof (sd->seesd_sun_sno)] = '\0'; return (0); } int mem_get_serid(const char *device, char *serid, size_t seridsz) { char buf[8192]; int fd; ssize_t sz; if ((fd = open(device, O_RDONLY)) < 0) return (-1); /* errno is set for us */ if ((sz = read(fd, buf, sizeof (buf))) < 0) { int err = errno; (void) close(fd); return (fmd_fmri_set_errno(err)); } (void) close(fd); switch (sz) { case BUFSIZ_SPD: return (mem_get_spd_serid(buf, BUFSIZ_SPD, serid, seridsz)); case BUFSIZ_SEEPROM: return (mem_get_seeprom_serid(buf, BUFSIZ_SEEPROM, serid, seridsz)); default: return (fmd_fmri_set_errno(EINVAL)); } } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MEM_SEEPROM_H #define _MEM_SEEPROM_H /* * Layout of SEEPROM data * * XXX need cite */ #include #ifdef __cplusplus extern "C" { #endif /* * Care must be taken when accessing these structures, as the SEEPROM source * data does not have an alignment requirement. */ typedef struct seeprom_seg_sd { uint32_t seesd_header; uint32_t seesd_tstamp; char seesd_frudesc[80]; char seesd_mfgloc[64]; char seesd_sun_pno[7]; char seesd_sun_sno[6]; uint8_t seesd_vendorhi; uint8_t seesd_vendorlo; char seesd_hwdash[2]; char seesd_hwrev[2]; char seesd_fruname[16]; } seeprom_seg_sd_t; typedef struct seeprom_seg { char sees_name[2]; uint16_t sees_prothi; uint16_t sees_protlo; uint16_t sees_segoff; uint16_t sees_seglen; } seeprom_seg_t; typedef struct seeprom_container { uint8_t seec_tag; uint8_t seec_verhi; uint8_t seec_verlo; uint8_t seec_contsz; uint8_t seec_crc8; uint8_t seec_nsegs; } seeprom_container_t; #ifdef __cplusplus } #endif #endif /* _MEM_SEEPROM_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #ifndef _MEM_SPD_H #define _MEM_SPD_H /* * Layout of SPD-format data, as per PICL. */ #include #ifdef __cplusplus extern "C" { #endif typedef struct spd_data { uint8_t spd_len; /* bytes written by manufacturer */ uint8_t spd_max_len; /* total available prom space */ uint8_t memory_type; /* e.g. SDRAM DDR = 0x07 */ uint8_t n_rows; /* row address bits */ uint8_t n_cols; /* column address bits */ uint8_t n_mod_rows; /* number of module rows */ uint8_t ls_data_width; /* e.g. 72 bits */ uint8_t ms_data_width; uint8_t vddq_if; /* e.g. SSTL 2.5V = 0x04 */ uint8_t cycle_time25; /* cycle time at CAS latency 2.5 */ uint8_t access_time25; uint8_t config; /* e.g. ECC = 0x02 */ uint8_t refresh; /* e.g. 7.8uS & self refresh = 0x82 */ uint8_t primary_width; uint8_t err_chk_width; uint8_t tCCD; uint8_t burst_lengths; /* e.g. 2,4,8 = 0x0e */ uint8_t n_banks; uint8_t cas_lat; uint8_t cs_lat; uint8_t we_lat; uint8_t mod_attrs; uint8_t dev_attrs; uint8_t cycle_time20; /* cycle time at CAS latency 2.0 */ uint8_t access_time20; uint8_t cycle_time15; uint8_t access_time15; uint8_t tRP; uint8_t tRRD; uint8_t tRCD; uint8_t tRAS; uint8_t mod_row_density; uint8_t addr_ip_setup; uint8_t addr_ip_hold; uint8_t data_ip_setup; uint8_t data_ip_hold; uint8_t superset[62 - 36]; uint8_t spd_rev; uint8_t chksum_0_62; uint8_t jedec[8]; uint8_t manu_loc; uint8_t manu_part_no[91 - 73]; uint8_t manu_rev_pcb; uint8_t manu_rev_comp; uint8_t manu_year; uint8_t manu_week; uint8_t asmb_serial_no[4]; uint8_t manu_specific[128 - 99]; } spd_data_t; #ifdef __cplusplus } #endif #endif /* _MEM_SPD_H */ /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2019 Peter Tribble. */ #include #include #include #include #include #include #define ISHCUNUM(unum) (strncmp(unum, "hc:/", 4) == 0) /* * Given a DIMM or bank unum, mem_unum_burst will break it apart into individual * DIMM names. If it's a DIMM, one name will be returned. If it's a bank, the * unums for the individual DIMMs will be returned. * * Plain J-number DIMM and bank unums are simple. J DIMMs have one J number. J * banks have multiple whitespace-separated J numbers. * * The others are more complex, and consist of a common portion c, a colon, and * a DIMM-specific portion d. DIMMs are of the form "c: d", while banks are of * the form "c: d d ...". The patterns are designed to handle the complex case, * but also handle the simple ones as an afterthought. bd_pat is used to * match specific styles of unum. In bd_pat, the first %n indicates the end of * the common portion ("c" above). The second %n marks the beginning of the * repetitive portion ("d" above). The third %n is used to determine whether or * not the entire pattern matched. bd_reppat is used to match instances of the * repetitive part. * * sscanf is your disturbingly powerful friend. * * The "bd_subst" element of the bank_dimm structure was added for Ontario * in order to accommodate its bank string names. Previously, to convert * from a bank representation ... * we concatenated the common piece with each dimm-specific piece in turn, * possibly deleting some characters in between. Ontario is the first * platform which requires that characters be substituted (like a vi s/1/2/) * in place of characters deleted. "bd_subst" represents the character(s) * to be substituted between the common piece and each dimm-specific piece * as part of the bursting. For prior platforms, this value is skipped. * * Example: * input: "MB/CMP0/CH3: R1/D0/J1901 R1/D1/J2001" * outputs: "MB/CMP0/CH3/R1/D0/J1901", "MB/CMP0/CH3/R1/D1/J2001" */ typedef struct bank_dimm { const char *bd_pat; const char *bd_reppat; const char *bd_subst; } bank_dimm_t; static const bank_dimm_t bank_dimm[] = { { "%n%nJ%*4d%n", " J%*4d%n" }, { "MB/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, { "MB/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, { "C%*d/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, { "C%*d/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, { "Slot %*c: %n%nJ%*4d%n", " J%*4d%n" }, { "%n%nDIMM%*d%n", " DIMM%*d%n" }, { "MB/%nDIMM%*d MB/DIMM%*d: %n%n", " DIMM%*d%n" }, { "MB/%nDIMM%*d:%n%n", " DIMM%*d%n" }, { "MB/CMP%*d/CH%*d%n:%n%n", " R%*d/D%*d/J%*4d%n", "/" }, { "MB/CMP%*d/CH%*d%n%n%n", "/R%*d/D%*d/J%*4d%n" }, { "MB/C%*d/P%*d/%nB%*d:%n%n", " B%*d/D%*d%n" }, { "MB/C%*d/P%*d/%nB%*d/D%*d:%n%n", " B%*d/D%*d%n" }, { "/MBU_A/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, { "/MBU_B/MEMB%*d/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, { "/MBU_A/%n%nMEM%*d%*1c%n", " MEM%*d%*1c%n" }, { "/CMU%*2d/%n%nMEM%*2d%*1c%n", " MEM%*2d%*1c%n" }, { "MB/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/" }, { "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", "MB/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, { "%n%nMB/CMP%*d/BR%*d/CH%*d/D%*d%n", "MB/CMP%*d/BR%*d/CH%*d/D%*d%n" }, { "MB/CPU%*d/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/"}, { "MB/MEM%*d/CMP%*d/BR%*d%n:%n%n", " CH%*d/D%*d/J%*4d%n", "/"}, { "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, { "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n", "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d/J%*4d%n" }, { "%n%nMB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n", "MB/MEM%*d/CMP%*d/BR%*d/CH%*d/D%*d%n" }, { "%n%nMB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n", "MB/CPU%*d/CMP%*d/BR%*d/CH%*d/D%*d%n" }, { NULL } }; /* * Burst Serengeti-style unums. * A DIMM unum string is expected to be in this form: * "[/N0/]SB12/P0/B0/D2 [J13500]" * A bank unum string is expected to be in this form: * "[/N0/]SB12/P0/B0 [J13500, ...]" */ static int mem_unum_burst_sgsc(const char *pat, char ***dimmsp, size_t *ndimmsp) { char buf[64]; char **dimms; char *base; const char *c; char *copy; size_t copysz; int i; /* * No expansion is required for a DIMM unum */ if (strchr(pat, 'D') != NULL) { dimms = fmd_fmri_alloc(sizeof (char *)); dimms[0] = fmd_fmri_strdup(pat); *dimmsp = dimms; *ndimmsp = 1; return (0); } /* * strtok is destructive so we need to work with * a copy and keep track of the size allocated. */ copysz = strlen(pat) + 1; copy = fmd_fmri_alloc(copysz); (void) strcpy(copy, pat); base = strtok(copy, " "); /* There are four DIMMs in a bank */ dimms = fmd_fmri_alloc(sizeof (char *) * 4); for (i = 0; i < 4; i++) { (void) snprintf(buf, sizeof (buf), "%s/D%d", base, i); if ((c = strtok(NULL, " ")) != NULL) { size_t len = strlen(buf); (void) snprintf(buf + len, sizeof (buf) - len, " %s", c); } dimms[i] = fmd_fmri_strdup(buf); } fmd_fmri_free(copy, copysz); *dimmsp = dimms; *ndimmsp = 4; return (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); /* * Set errno to ENOTSUP and return -1. This allows support for DIMMs * with unknown unum strings and/or serial numbers. The only consumer * of mem_unum_burst_pattern() that cares/checks for the returned * errno is fmd_fmri_expand(). */ return (fmd_fmri_set_errno(ENOTSUP)); } int mem_unum_burst(const char *pat, char ***dimmsp, size_t *ndimmsp) { const char *platform = fmd_fmri_get_platform(); /* * Call mem_unum_burst_sgsc() for Serengeti and * Lightweight 8 platforms. Call mem_unum_burst_pattern() * for all other platforms. */ if (strcmp(platform, "SUNW,Sun-Fire") == 0 || strcmp(platform, "SUNW,Netra-T12") == 0) return (mem_unum_burst_sgsc(pat, dimmsp, ndimmsp)); else return (mem_unum_burst_pattern(pat, dimmsp, ndimmsp)); } /* * The unum containership operation is designed to tell the caller whether a * given FMRI contains another. In the case of this plugin, we tell the caller * whether a given memory FMRI (usually a bank) contains another (usually a * DIMM). We do this in one of two ways, depending on the platform. For most * platforms, we can use the bursting routine to generate the list of member * unums from the container unum. Membership can then be determined by * searching the bursted list for the containee's unum. * * Some platforms, however, cannot be bursted, as their bank unums do not * contain all of the information needed to generate the complete list of * member DIMM unums. For these unums, we must make do with a substring * comparison. */ 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); } static int unum_strip_one_jnum(const char *unum, uint_t *endp) { char *c; int i; if ((c = strrchr(unum, 'J')) == NULL) return (0); while (c > unum && isspace(c[-1])) c--; (void) sscanf(c, " J%*[0-9] %n", &i); if (i == 0 || (uintptr_t)(c - unum) + i != strlen(unum)) return (0); *endp = (uint_t)(c - unum); return (1); } 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); } typedef int unum_cmptor_f(const char *, const char *); static unum_cmptor_f *const unum_cmptors[] = { unum_contains_bypat, unum_contains_bysubstr }; int mem_unum_contains(const char *erunum, const char *eeunum) { static int cmptor = 0; int rc; while (isspace(*erunum)) erunum++; while (isspace(*eeunum)) eeunum++; if ((rc = unum_cmptors[cmptor](erunum, eeunum)) >= 0) return (rc); if ((rc = unum_cmptors[cmptor == 0](erunum, eeunum)) >= 0) { /* * We succeeded with the non-default comparator. Change the * default so we use the correct one next time. */ cmptor = (cmptor == 0); } return (rc); } /* * If an asru has a unum string that is an hc path string then return * a new nvl (to be freed by the caller) that is a duplicate of the * original but with an additional member of a reconstituted hc fmri. */ int mem_unum_rewrite(nvlist_t *nvl, nvlist_t **rnvl) { int err; char *unumstr; nvlist_t *unum; struct topo_hdl *thp; if (nvlist_lookup_string(nvl, FM_FMRI_MEM_UNUM, &unumstr) != 0 || !ISHCUNUM(unumstr)) return (0); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (EINVAL); if (topo_fmri_str2nvl(thp, unumstr, &unum, &err) != 0) { fmd_fmri_topo_rele(thp); return (EINVAL); } fmd_fmri_topo_rele(thp); if ((err = nvlist_dup(nvl, rnvl, 0)) != 0) { nvlist_free(unum); return (err); } err = nvlist_add_nvlist(*rnvl, FM_FMRI_MEM_UNUM "-fmri", unum); nvlist_free(unum); if (err != 0) nvlist_free(*rnvl); return (err); } /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include void mem_strarray_free(char **arr, size_t dim) { int i; for (i = 0; i < dim; i++) { if (arr[i] != NULL) fmd_fmri_strfree(arr[i]); } fmd_fmri_free(arr, sizeof (char *) * dim); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com include $(SRC)/Makefile.master.64 # Hammerhead: 64-bit only - flatten FM library paths LDLIBS += \ -L$(ROOTLIB)/fm -ltopo LDFLAGS += -R/usr/lib/fm include ../../Makefile.targ install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include 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); } /* * fmd_fmri_present() is called by fmadm to determine if a faulty resource * is still present in the system. We just return true by default, as we have no * real way to look up the component in the system configuration. */ /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /*ARGSUSED*/ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /* * fmd_fmri_unusable() is called by fmadm to determine if a faulty ASRU * is usable. In general we don't expect to get ASRUs in this scheme, * so it's unlikely this routine will get called. In case it does, * though, we just return false by default, as we have no real way to * find the component or determine the component's usability. */ /*ARGSUSED*/ int fmd_fmri_unusable(nvlist_t *nvl) { return (0); } # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2023 Oxide Computer Company # include $(SRC)/cmd/Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # This file and its contents are supplied under the terms of the # Common Development and Distribution License ("CDDL"), version 1.0. # You may only use this file in accordance with the terms of version # 1.0 of the CDDL. # # A full copy of the text of the CDDL should have accompanied this # source. A copy of the CDDL is also available via the Internet at # http://www.illumos.org/license/CDDL. # # # Copyright 2023 Oxide Computer Company # include ../../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -ltopo # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm install: all $(ROOTPROG64) /* * This file and its contents are supplied under the terms of the * Common Development and Distribution License ("CDDL"), version 1.0. * You may only use this file in accordance with the terms of version * 1.0 of the CDDL. * * A full copy of the text of the CDDL should have accompanied this * source. A copy of the CDDL is also available via the Internet at * http://www.illumos.org/license/CDDL. */ /* * Copyright 2023 Oxide Computer Company */ #include #include #include 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)); } len = snprintf(buf, buflen, "%s", str); topo_hdl_strfree(thp, str); fmd_fmri_topo_rele(thp); return (len); } /* * fmd_fmri_present() is called by fmadm to determine if a faulty resource * is still present in the system. We just return true for now, but could * extend this in the future to look at PCI configuration space. */ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /* * fmd_fmri_replaced() is called by fmadm to determine if a resource has been * replaced. We always return unknown for now but this should be extended in * the future as it is possible to determine if devices have been replaced by, * for instance, checking the serial number. */ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /* * fmd_fmri_unusable() is called by fmadm to determine if a faulty ASRU * is unusable. */ int fmd_fmri_unusable(nvlist_t *nvl) { topo_hdl_t *thp; int unusable, err; 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); if (err == ETOPO_METHOD_NOTSUP) return (0); return (unusable); } int fmd_fmri_init(void) { return (0); } void fmd_fmri_fini(void) { } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # ident "%Z%%M% %I% %E% SMI" # include ../../Makefile.com include $(SRC)/Makefile.master.64 # Hammerhead: 64-bit only - flatten FM library paths LDLIBS += \ -L$(ROOTLIB)/fm -ltopo LDFLAGS += -R/usr/lib/fm include ../../Makefile.targ install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include 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); } /* * fmd_fmri_present() is called by fmadm to determine if a faulty resource * is still present in the system. We just return true by default, as we have no * real way to look up the component in the system configuration. */ /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /*ARGSUSED*/ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /* * fmd_fmri_unusable() is called by fmadm to determine if a faulty ASRU * is usable. In general we don't expect to get ASRUs in this scheme, * so it's unlikely this routine will get called. In case it does, * though, we just return false by default, as we have no real way to * find the component or determine the component's usability. */ /*ARGSUSED*/ int fmd_fmri_unusable(nvlist_t *nvl) { return (0); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../../Makefile.com # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # include ../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -ltopo # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm LINTFLAGS += -L$(ROOT)/usr/lib/fm install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include int fmd_fmri_init(void) { return (0); } void fmd_fmri_fini(void) { } 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); } /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { uint8_t version; int err, present; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_SVC_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); if ((thp = fmd_fmri_topo_hold(TOPO_VERSION)) == NULL) return (fmd_fmri_set_errno(EINVAL)); present = topo_fmri_present(thp, nvl, &err); fmd_fmri_topo_rele(thp); return (present); } int fmd_fmri_replaced(nvlist_t *nvl) { uint8_t version; int err, replaced; topo_hdl_t *thp; if (nvlist_lookup_uint8(nvl, FM_VERSION, &version) != 0 || version > FM_SVC_SCHEME_VERSION) 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_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); } /*ARGSUSED*/ 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_SVC_SCHEME_VERSION) return (fmd_fmri_set_errno(EINVAL)); 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); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # include ../../Makefile.com # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. # include ../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -ltopo # Hammerhead: 64-bit only - flatten FM library paths LDFLAGS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm LINTFLAGS += -L$(ROOT)/usr/lib/fm install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ #include #include #include #include #include int fmd_fmri_init(void) { return (0); } void fmd_fmri_fini(void) { } 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); } /*ARGSUSED*/ int fmd_fmri_present(nvlist_t *nvl) { return (1); } /*ARGSUSED*/ int fmd_fmri_replaced(nvlist_t *nvl) { return (FMD_OBJ_STATE_UNKNOWN); } /*ARGSUSED*/ int fmd_fmri_service_state(nvlist_t *nvl) { return (FMD_SERVICE_STATE_UNKNOWN); } /*ARGSUSED*/ int fmd_fmri_unusable(nvlist_t *nvl) { return (0); } # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" include ../../../Makefile.cmd # Hammerhead: amd64-only SUBDIRS = $(MACH64) include ../../Makefile.subdirs # # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # #ident "%Z%%M% %I% %E% SMI" include ../../Makefile.com include $(SRC)/Makefile.master.64 include ../../Makefile.targ LDLIBS += -lzfs install: all $(ROOTPROG64) /* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2010 Nexenta Systems, Inc. All rights reserved. */ #include #include #include typedef struct cbdata { uint64_t cb_guid; zpool_handle_t *cb_pool; } cbdata_t; libzfs_handle_t *g_zfs; static int find_pool(zpool_handle_t *zhp, void *data) { cbdata_t *cbp = data; if (zpool_get_prop_int(zhp, ZPOOL_PROP_GUID, NULL) == cbp->cb_guid) { cbp->cb_pool = zhp; return (1); } zpool_close(zhp); return (0); } ssize_t fmd_fmri_nvl2str(nvlist_t *nvl, char *buf, size_t buflen) { uint64_t pool_guid, vdev_guid; cbdata_t cb; ssize_t len; const char *name; char guidbuf[64]; (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); /* * Attempt to convert the pool guid to a name. */ cb.cb_guid = pool_guid; cb.cb_pool = NULL; if (zpool_iter(g_zfs, find_pool, &cb) == 1) { name = zpool_get_name(cb.cb_pool); } else { (void) snprintf(guidbuf, sizeof (guidbuf), "%llx", pool_guid); name = guidbuf; } if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) == 0) len = snprintf(buf, buflen, "%s://pool=%s/vdev=%llx", FM_FMRI_SCHEME_ZFS, name, vdev_guid); else len = snprintf(buf, buflen, "%s://pool=%s", FM_FMRI_SCHEME_ZFS, name); if (cb.cb_pool) zpool_close(cb.cb_pool); return (len); } static nvlist_t * find_vdev_iter(nvlist_t *nv, uint64_t search) { uint_t c, children; nvlist_t **child; uint64_t guid; nvlist_t *ret; (void) nvlist_lookup_uint64(nv, ZPOOL_CONFIG_GUID, &guid); if (search == guid) return (nv); if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_CHILDREN, &child, &children) == 0) { for (c = 0; c < children; c++) if ((ret = find_vdev_iter(child[c], search)) != 0) return (ret); } if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_L2CACHE, &child, &children) == 0) { for (c = 0; c < children; c++) if ((ret = find_vdev_iter(child[c], search)) != 0) return (ret); } if (nvlist_lookup_nvlist_array(nv, ZPOOL_CONFIG_SPARES, &child, &children) == 0) { for (c = 0; c < children; c++) if ((ret = find_vdev_iter(child[c], search)) != 0) return (ret); } return (NULL); } static nvlist_t * find_vdev(zpool_handle_t *zhp, uint64_t guid) { nvlist_t *config, *nvroot; config = zpool_get_config(zhp, NULL); (void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &nvroot); return (find_vdev_iter(nvroot, guid)); } int fmd_fmri_present(nvlist_t *nvl) { uint64_t pool_guid, vdev_guid; cbdata_t cb; int ret; (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); cb.cb_guid = pool_guid; cb.cb_pool = NULL; if (zpool_iter(g_zfs, find_pool, &cb) != 1) return (0); if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { zpool_close(cb.cb_pool); return (1); } ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL); zpool_close(cb.cb_pool); return (ret); } int fmd_fmri_replaced(nvlist_t *nvl) { uint64_t pool_guid, vdev_guid; cbdata_t cb; int ret; (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); cb.cb_guid = pool_guid; cb.cb_pool = NULL; if (zpool_iter(g_zfs, find_pool, &cb) != 1) return (FMD_OBJ_STATE_NOT_PRESENT); if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { zpool_close(cb.cb_pool); return (FMD_OBJ_STATE_STILL_PRESENT); } ret = (find_vdev(cb.cb_pool, vdev_guid) != NULL) ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_NOT_PRESENT; zpool_close(cb.cb_pool); return (ret); } int fmd_fmri_unusable(nvlist_t *nvl) { uint64_t pool_guid, vdev_guid; cbdata_t cb; nvlist_t *vd; int ret; (void) nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_POOL, &pool_guid); cb.cb_guid = pool_guid; cb.cb_pool = NULL; if (zpool_iter(g_zfs, find_pool, &cb) != 1) return (1); if (nvlist_lookup_uint64(nvl, FM_FMRI_ZFS_VDEV, &vdev_guid) != 0) { ret = (zpool_get_state(cb.cb_pool) == POOL_STATE_UNAVAIL); zpool_close(cb.cb_pool); return (ret); } vd = find_vdev(cb.cb_pool, vdev_guid); if (vd == NULL) { ret = 1; } else { vdev_stat_t *vs; uint_t c; (void) nvlist_lookup_uint64_array(vd, ZPOOL_CONFIG_VDEV_STATS, (uint64_t **)&vs, &c); ret = (vs->vs_state < VDEV_STATE_DEGRADED); } zpool_close(cb.cb_pool); return (ret); } int fmd_fmri_init(void) { g_zfs = libzfs_init(); if (g_zfs == NULL) return (-1); else return (0); } void fmd_fmri_fini(void) { if (g_zfs) libzfs_fini(g_zfs); }