diff options
14 files changed, 732 insertions, 35 deletions
@@ -10157,7 +10157,11 @@ d usr/platform/i86pc/lib/fm/topo 0755 root sys d usr/platform/i86pc/lib/fm/topo/maps 0755 root sys f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-1101-disk-hc-topology.xml 0444 root sys s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3101-hc-topology.xml=./SSG-2028R-ACR24L-hc-topology.xml -s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3102-hc-topology.xml=./SSG-2028R-ACR24L-hc-topology.xml +s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3102-hc-topology.xml=./SSG-2028R-ACR24L-hc-topology.xml +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3301-hc-topology.xml 0444 root sys +s usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3302-hc-topology.xml=./Joyent-Compute-Platform-3301-hc-topology.xml +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-330x-chassis-hc-topology.xml 0444 root sys +f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-330x-fan-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-chassis-hc-topology.xml 0444 root sys f usr/platform/i86pc/lib/fm/topo/maps/Joyent-Storage-Platform-7001-slot-hc-topology.xml 0444 root sys diff --git a/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c b/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c index 6bf4da305a..db8715ac01 100644 --- a/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c +++ b/usr/src/cmd/fm/modules/common/sensor-transport/sensor_transport.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, Joyent, Inc. */ #include <fm/fmd_api.h> @@ -56,6 +57,7 @@ typedef struct sensor_transport { * we'll tolerate before sending an ereport. */ uint32_t st_tolerance; + nvlist_t *st_spoofs; } sensor_transport_t; typedef struct st_stats { @@ -72,6 +74,7 @@ st_stats_t st_stats = { static int st_check_component_complaints; static int have_complained; +static char *spoof_prop = NULL; static int st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) @@ -83,7 +86,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) char *fmri; int err, ret; int32_t last_source, source = -1; - boolean_t nonrecov, faulted, predictive, source_diff; + boolean_t nonrecov, faulted, predictive, source_diff, injected; nvpair_t *nvp; uint64_t ena; nvlist_t *event; @@ -117,7 +120,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) } if (topo_method_invoke(node, TOPO_METH_SENSOR_FAILURE, - TOPO_METH_SENSOR_FAILURE_VERSION, NULL, &nvl, &err) != 0) { + TOPO_METH_SENSOR_FAILURE_VERSION, stp->st_spoofs, &nvl, &err) != + 0) { if (err == ETOPO_METHOD_NOTSUP) { st_check_component_complaints++; if (!have_complained) { @@ -131,7 +135,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) nvl = NULL; } - if (topo_node_fru(node, &fru, NULL, NULL) != 0) { + if (topo_node_fru(node, &fru, NULL, &err) != 0) { st_stats.st_bad_fmri.fmds_value.ui64++; nvlist_free(nvl); nvlist_free(rsrc); @@ -148,7 +152,7 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) nvlist_free(fru); - faulted = nonrecov = source_diff = B_FALSE; + faulted = nonrecov = source_diff = injected = B_FALSE; predictive = B_TRUE; if (nvl != NULL) { nvp = NULL; @@ -173,6 +177,9 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) * * 3) source will be set to unknown unless all facility * nodes agree on the source + * + * 4) injected defaults to false, but will be set to + * true if any of the sensor states were injected. */ if (nonrecov == B_FALSE) if (nvlist_lookup_boolean_value(props, @@ -182,6 +189,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) if (nvlist_lookup_boolean_value(props, "predictive", &predictive) != 0) predictive = B_FALSE; + (void) nvlist_lookup_boolean_value(props, + "injected", &injected); last_source = source; if (nvlist_lookup_uint32(props, "source", @@ -260,7 +269,8 @@ st_check_component(topo_hdl_t *thp, tnode_t *node, void *arg) (void) nvlist_add_uint64(event, FM_EREPORT_ENA, ena); (void) nvlist_add_nvlist(event, FM_EREPORT_DETECTOR, rsrc); - + (void) nvlist_add_boolean_value(event, "__injected", + injected); fmd_xprt_post(hdl, stp->st_xprt, event, 0); fmd_hdl_debug(hdl, "posted ereport: %s", ST_EREPORT_CLASS); @@ -351,9 +361,74 @@ st_timeout(fmd_hdl_t *hdl, id_t id, void *data) stp->st_timer = fmd_timer_install(hdl, NULL, NULL, stp->st_interval); } +/* + * Parse the value of the spoof-sensor-state module property and store the + * result in an nvlist of nvlists. The format of the value is 3-tuple, + * delimited by colons, as follows: + * + * FMRIPATTERN:SENSORNAME:SENSORSTATE;... + * + * where FMRIPATTERN can be a string with wildcards that matches the FMRI + * of a node associated with the target sensor facility. + * + * where SENSORNAME is the node name of the target sensor facility + * + * where SENSORSTATE is the desired sensor state value to spoof. + * + * Multiple tuples can be specifed, delimited by semicolons. + * + * If any errors are encountered while parsing the value, all parsing is + * ceased and an ereport will be generated indicating a failure to parse + * the value. + */ +/*ARGSUSED*/ +static int +parse_spoof_param(fmd_hdl_t *hdl, char *param, sensor_transport_t *stp) +{ + char *sensor, *last_sensor, *field, *last_field; + nvlist_t *spoof; + + if (nvlist_alloc(&stp->st_spoofs, NV_UNIQUE_NAME, 0) != NULL) { + return (-1); + } + + sensor = strtok_r(param, ";", &last_sensor); + while (sensor != NULL) { + if (nvlist_alloc(&spoof, NV_UNIQUE_NAME, 0) != 0) + goto err; + + if ((field = strtok_r(sensor, ":", &last_field)) == NULL || + nvlist_add_string(spoof, ST_SPOOF_FMRI, field) != 0) + goto err; + + if ((field = strtok_r(NULL, ":", &last_field)) == NULL || + nvlist_add_string(spoof, ST_SPOOF_SENSOR, field) != 0) + goto err; + + if ((field = strtok_r(NULL, ":", &last_field)) == NULL || + nvlist_add_uint32(spoof, ST_SPOOF_STATE, + strtol(field, NULL, 0)) != 0) + goto err; + + if (nvlist_add_nvlist(stp->st_spoofs, sensor, spoof) != 0) + goto err; + + spoof = NULL; + sensor = strtok_r(NULL, ";", &last_sensor); + } + + return (0); +err: + nvlist_free(spoof); + nvlist_free(stp->st_spoofs); + stp->st_spoofs = NULL; + return (-1); +} + static const fmd_prop_t fmd_props[] = { { "interval", FMD_TYPE_TIME, "1min" }, { "tolerance", FMD_TYPE_UINT32, "1" }, + { "spoof_sensor_state", FMD_TYPE_STRING, NULL }, { NULL, 0, NULL } }; @@ -397,6 +472,10 @@ _fmd_init(fmd_hdl_t *hdl) stp = fmd_hdl_zalloc(hdl, sizeof (sensor_transport_t), FMD_SLEEP); stp->st_interval = fmd_prop_get_int64(hdl, "interval"); stp->st_tolerance = fmd_prop_get_int32(hdl, "tolerance"); + spoof_prop = fmd_prop_get_string(hdl, "spoof_sensor_state"); + + if (spoof_prop != NULL && parse_spoof_param(hdl, spoof_prop, stp) != 0) + fmd_hdl_error(hdl, "Error parsing config file"); fmd_hdl_setspecific(hdl, stp); @@ -424,7 +503,8 @@ _fmd_fini(fmd_hdl_t *hdl) fmd_hdl_strfree(hdl, sfp->sf_fru); fmd_hdl_free(hdl, sfp, sizeof (sensor_fault_t)); } - + nvlist_free(stp->st_spoofs); fmd_hdl_free(hdl, stp, sizeof (sensor_transport_t)); } + fmd_prop_free_string(hdl, spoof_prop); } diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.c b/usr/src/lib/fm/topo/libtopo/common/topo_method.c index 8d36e96d9a..728d76ad82 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_method.c +++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.c @@ -22,11 +22,15 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. + */ #include <pthread.h> #include <assert.h> #include <errno.h> #include <dirent.h> +#include <fnmatch.h> #include <limits.h> #include <alloca.h> #include <unistd.h> @@ -358,6 +362,44 @@ topo_sensor_failed(int32_t type, uint32_t state, struct sensor_errinfo *seinfo) return (failed); } +static boolean_t +topo_spoof_apply(topo_hdl_t *thp, tnode_t *node, tnode_t *facnode, + nvlist_t *in, uint32_t *state) +{ + nvpair_t *elem = NULL; + nvlist_t *spoof, *rsrc = NULL; + char *fmrimatch, *fmri, *facmatch; + uint32_t spoof_state; + int err; + + while ((elem = nvlist_next_nvpair(in, elem)) != NULL) { + if (nvpair_value_nvlist(elem, &spoof) != 0) + return (B_FALSE); + + if (nvlist_lookup_string(spoof, ST_SPOOF_FMRI, &fmrimatch) != + 0 || nvlist_lookup_string(spoof, ST_SPOOF_SENSOR, + &facmatch) != 0 || nvlist_lookup_uint32(spoof, + ST_SPOOF_STATE, &spoof_state) != 0) + continue; + + if (topo_node_resource(node, &rsrc, &err) != 0 || + topo_fmri_nvl2str(thp, rsrc, &fmri, &err) != 0) { + nvlist_free(rsrc); + continue; + } + nvlist_free(rsrc); + + if (fnmatch(fmrimatch, fmri, 0) == 0 && + strcmp(facmatch, topo_node_name(facnode)) == 0) { + *state = spoof_state; + topo_hdl_strfree(thp, fmri); + return (B_TRUE); + } + topo_hdl_strfree(thp, fmri); + } + return (B_FALSE); +} + /* * Determine whether there are any sensors indicating failure. This function * is used internally to determine whether a given component is usable, as well @@ -375,13 +417,16 @@ topo_sensor_failed(int32_t type, uint32_t state, struct sensor_errinfo *seinfo) * non-recoverable (the unit is out of service). The default is * critical failure, which indicates a fault but the unit is still * operating. + * + * injected + * + * Boolean value indicating that the sensor state was injected. */ /*ARGSUSED*/ int topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t *in, nvlist_t **out) { - const char *name = topo_node_name(node); topo_faclist_t faclist, *fp; int err; nvlist_t *nvl, *props, *propval, *tmp; @@ -390,12 +435,9 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, nvpair_t *elem; double reading; char *propname; - boolean_t has_reading; + boolean_t has_reading, is_spoofed = B_FALSE; struct sensor_errinfo seinfo; - if (strcmp(name, PSU) != 0 && strcmp(name, FAN) != 0) - return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); - if (topo_node_facility(mod->tm_hdl, node, TOPO_FAC_TYPE_SENSOR, TOPO_FAC_TYPE_ANY, &faclist, &err) != 0) return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); @@ -441,6 +483,10 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, } } + if (in != NULL) + is_spoofed = topo_spoof_apply(mod->tm_hdl, node, + fp->tf_node, in, &state); + if (topo_sensor_failed(type, state, &seinfo)) { tmp = NULL; if (topo_mod_nvalloc(mod, &tmp, NV_UNIQUE_NAME) != 0 || @@ -456,6 +502,8 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, "predictive", seinfo.se_predictive) != 0 || nvlist_add_uint32(tmp, "source", seinfo.se_src) != 0 || + nvlist_add_boolean_value(nvl, "injected", + is_spoofed) != 0 || (has_reading && nvlist_add_double(tmp, TOPO_SENSOR_READING, reading) != 0) || nvlist_add_nvlist(nvl, topo_node_name(fp->tf_node), @@ -472,6 +520,7 @@ topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, } nvlist_free(props); + is_spoofed = B_FALSE; } *out = nvl; diff --git a/usr/src/lib/fm/topo/libtopo/common/topo_method.h b/usr/src/lib/fm/topo/libtopo/common/topo_method.h index ed0733375d..3cf14b92ec 100644 --- a/usr/src/lib/fm/topo/libtopo/common/topo_method.h +++ b/usr/src/lib/fm/topo/libtopo/common/topo_method.h @@ -23,7 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ - +/* + * Copyright (c) 2018, Joyent, Inc. + */ #ifndef _TOPO_METHOD_H #define _TOPO_METHOD_H @@ -54,6 +56,14 @@ extern int topo_prop_method_version_register(tnode_t *, const char *, int *); /* + * These are for the private consumption of the sensor-transport fmd plugin + * and topo_method_sensor_failure() + */ +#define ST_SPOOF_FMRI "spoof_resource_fmri" +#define ST_SPOOF_SENSOR "spoof_sensor_name" +#define ST_SPOOF_STATE "spoof_sensor_state" + +/* * FMRI methods */ #define TOPO_METH_ASRU_COMPUTE "topo_asru_compute" diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-3301-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-3301-hc-topology.xml new file mode 100644 index 0000000000..000ed261a8 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-3301-hc-topology.xml @@ -0,0 +1,251 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + 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 (c) 2018, Joyent, Inc. +--> + +<topology name='i86pc' scheme='hc'> + + <range name='motherboard' min='0' max='0'> + <enum-method name='smbios' version='1' /> + <node instance='0' static='true'> + <fac-enum provider='fac_prov_ipmi' /> + <facility name='3.3V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='3.3V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='5V AUX PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='5V AUX PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='1.05V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='1.05V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='BP0 5V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='BP0 5V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='5V SWITCH PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='5V SWITCH PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='VCCIO PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='VCCIO PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='NDC PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='2.5V AUX PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='1.5V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='1.5V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='BP1 5V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='BP1 5V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='BP2 5V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='BP2 5V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='1.5V AUX PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='1.5V AUX PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='1.05V PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='1.05V PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <facility name='DIMM PG' type='sensor' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='269' /> + <propval name='sensor-class' type='string' value='discrete' /> + <propval name='entity_ref' type='string_array' > + <propitem value='DIMM PG' /> + </propval> + <propmethod name='ipmi_sensor_state' version='0' + propname='state' proptype='uint32' > + </propmethod> + </propgroup> + </facility> + <propgroup name='protocol' version='1' + name-stability='Private' data-stability='Private' > + <propval name='label' type='string' value='MB' /> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-id' type='uint32' value='7' /> + <propval name='entity-instance' type='uint32' value='1' /> + <propval name='entity-list' type='string_array' > + <propitem value='CMOS Battery' /> + <propitem value='Dedicated NIC' /> + <propitem value='LCD Cable Pres' /> + <propitem value='NDC PG' /> + <propitem value='Riser Config Err' /> + <propitem value='Riser 2 Presence' /> + <propitem value='Riser 3 Presence' /> + <propitem value='USB Cable Pres' /> + <propitem value='VGA Cable Pres' /> + </propval> + </propgroup> + + </node> <!-- motherboard --> + + <dependents grouping='children'> + <range name='chip' min='0' max='1'> + <enum-method name='chip' version='1' /> + </range> + <range name='hostbridge' min='0' max='254'> + <enum-method name='hostbridge' version='1' /> + </range> + <range name='sp' min='0' max='0'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='slot' min='0' max='23'> + <enum-method name='smbios' version='1' /> + </range> + </dependents> + + </range> + + <range name='chassis' min='0' max='0'> + <propmap name='Joyent-Compute-Platform-330x-chassis' /> + + <dependents grouping='children'> + + <range name='psu' min='0' max='1'> + <enum-method name='ipmi' version='1' /> + </range> + <range name='fan' min='0' max='5'> + <propmap name='Joyent-Compute-Platform-330x-fan' /> + </range> + + </dependents> + + </range> + + <range name='ses-enclosure' min='0' max='1'> + <enum-method name='ses' version='1' /> + </range> + +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-chassis-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-chassis-hc-topology.xml new file mode 100644 index 0000000000..20dbc301eb --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-chassis-hc-topology.xml @@ -0,0 +1,43 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + 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 (c) 2018, Joyent, Inc. +--> + +<topology name='chassis' scheme='hc'> + <range name='chassis' min='0' max='0'> + <node instance='0'> + <fac-enum provider='fac_prov_ipmi' /> + <!-- + chassis locate LED + --> + <facility name='locate' type='indicator' provider='fac_prov_ipmi' > + <propgroup name='facility' version='1' name-stability='Private' + data-stability='Private' > + <propval name='type' type='uint32' value='1' /> + <propmethod name='chassis_ident_mode' version='0' + propname='mode' proptype='uint32' mutable='1' > + </propmethod> + </propgroup> + </facility> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Intrusion' /> + <propitem value='Pwr Consumption' /> + <propitem value='Inlet Temp' /> + <propitem value='Exhaust Temp' /> + </propval> + </propgroup> + </node> + </range> +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-fan-hc-topology.xml b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-fan-hc-topology.xml new file mode 100644 index 0000000000..5284971c19 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Joyent-Compute-Platform-330x-fan-hc-topology.xml @@ -0,0 +1,127 @@ +<?xml version="1.0"?> +<!DOCTYPE topology SYSTEM "/usr/share/lib/xml/dtd/topology.dtd.1"> +<!-- + 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 (c) 2018, Joyent, Inc. +--> + +<topology name='fan' scheme='hc'> + <range name='fan' min='0' max='5'> + <node instance='0'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 1' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan1' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + <node instance='1'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 2' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan2' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + <node instance='2'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 3' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan3' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + <node instance='3'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 4' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan4' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + <node instance='4'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 5' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan5' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + <node instance='5'> + <fac-enum provider='fac_prov_ipmi' /> + <propgroup name='protocol' version='1' name-stability='Private' + data-stability='Private'> + <propval name='label' type='string' value='FAN 6' /> + <propmethod name='ipmi_fru_fmri' version='0' propname='FRU' + proptype='fmri'> + <argval name='entity' type='string' value='self' /> + </propmethod> + </propgroup> + <propgroup name='ipmi' version='1' + name-stability='Private' data-stability='Private' > + <propval name='entity-list' type='string_array' > + <propitem value='Fan6' /> + </propval> + </propgroup> + <enum-method name='ipmi' version='1' /> + </node> + </range> +</topology> diff --git a/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Makefile b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Makefile new file mode 100644 index 0000000000..677a099c43 --- /dev/null +++ b/usr/src/lib/fm/topo/maps/Joyent,Joyent-Compute-Platform-330x/Makefile @@ -0,0 +1,49 @@ +# +# 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 (c) 2018, Joyent, Inc. +# + +ARCH = i86pc +CLASS = arch +DTDFILE = topology.dtd.1 +OTHER_VARIANTS = \ + Joyent-Compute-Platform-3302-hc-topology.xml + +ROOTJOYENTMAPS = $(OTHER_VARIANTS:%=$(arch_ROOTTOPOROOT)/%) + +TOPOFILE = \ + Joyent-Compute-Platform-3301-hc-topology.xml \ + Joyent-Compute-Platform-330x-chassis-hc-topology.xml \ + Joyent-Compute-Platform-330x-fan-hc-topology.xml + +SRCDIR = ../Joyent,Joyent-Compute-Platform-330x + +PLATFORM = Joyent-Compute-Platform-330x + +CLOBBERFILES += $(ROOTJOYENTMAPS) + +include ../Makefile.map + +install: $(ROOTJOYENTMAPS) + +# +# The JCP-3301 and JCP-3302 are essentially the same underlying hardware. The +# only significant difference is the JCP-3302 uses SSDs internally instead of +# traditional disks. As such, the same platform topo map should work for +# both platforms so we simply create a symlink from the JCP 3301 map for the +# JCP 3302. +# +$(ROOTJOYENTMAPS): Joyent-Compute-Platform-3301-hc-topology.xml + $(RM) $@ + $(SYMLINK) ./$? $@ + diff --git a/usr/src/lib/fm/topo/maps/Makefile b/usr/src/lib/fm/topo/maps/Makefile index 49b86186a1..f0e76ff531 100644 --- a/usr/src/lib/fm/topo/maps/Makefile +++ b/usr/src/lib/fm/topo/maps/Makefile @@ -51,6 +51,7 @@ i386_SUBDIRS = i86pc \ SUNW,Sun-Fire-X4540 \ SUNW,Sun-Fire-X4600-M2 \ Joyent,Joyent-Compute-Platform-1101 \ + Joyent,Joyent-Compute-Platform-330x \ Joyent,Joyent-Storage-Platform-7001 \ SMCI,SSG-2028R-ACR24L diff --git a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c index b394923833..434790fd65 100644 --- a/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c +++ b/usr/src/lib/fm/topo/modules/common/fac_prov_ipmi/fac_prov_ipmi.c @@ -113,6 +113,9 @@ static const topo_method_t ipmi_node_methods[] = { { "cs_ipmi_entity", TOPO_PROP_METH_DESC, TOPO_METH_DIMM_IPMI_ENTITY_VERSION, TOPO_STABILITY_INTERNAL, cs_ipmi_entity }, + { TOPO_METH_SENSOR_FAILURE, TOPO_METH_SENSOR_FAILURE_DESC, + TOPO_METH_SENSOR_FAILURE_VERSION, TOPO_STABILITY_INTERNAL, + topo_method_sensor_failure }, { NULL } }; @@ -351,10 +354,12 @@ ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers, ipmi_handle_t *hdl; int err, i; uint8_t sensor_num; + uint32_t e_id, e_inst; ipmi_sdr_full_sensor_t *fsensor; ipmi_sdr_compact_sensor_t *csensor; nvlist_t *nvl; boolean_t found_sdr = B_FALSE; + tnode_t *pnode; if (vers > TOPO_METH_IPMI_STATE_VERSION) return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); @@ -372,8 +377,18 @@ ipmi_sensor_state(topo_mod_t *mod, tnode_t *node, topo_version_t vers, return (-1); } + pnode = topo_node_parent(node); + if (topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_ID, &e_id, &err) != 0 || + topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_INST, &e_inst, &err) != 0) { + e_id = IPMI_ET_UNSPECIFIED; + e_inst = 0; + } + for (i = 0; i < nelems; i++) { - if ((sdr = ipmi_sdr_lookup(hdl, entity_refs[i])) != NULL) { + if ((sdr = ipmi_sdr_lookup_precise(hdl, entity_refs[i], + (uint8_t)e_id, (uint8_t)e_inst)) != NULL) { found_sdr = B_TRUE; break; } else @@ -438,12 +453,16 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers, char **entity_refs, reading_str[BUFSZ]; uint_t nelems; int err = 0, i; - ipmi_sdr_full_sensor_t *sensor; + ipmi_sdr_t *sdr = NULL; + ipmi_sdr_full_sensor_t *fsensor; ipmi_sensor_reading_t *reading; double conv_reading; ipmi_handle_t *hdl; nvlist_t *nvl; boolean_t found_sdr = B_FALSE; + uint8_t sensor_num; + uint32_t e_id, e_inst; + tnode_t *pnode; if (vers > TOPO_METH_IPMI_READING_VERSION) return (topo_mod_seterrno(mod, ETOPO_METHOD_VERNEW)); @@ -461,9 +480,18 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers, return (-1); } + pnode = topo_node_parent(node); + if (topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_ID, &e_id, &err) != 0 || + topo_prop_get_uint32(pnode, TOPO_PGROUP_IPMI, + TOPO_PROP_IPMI_ENTITY_INST, &e_inst, &err) != 0) { + e_id = IPMI_ET_UNSPECIFIED; + e_inst = 0; + } + for (i = 0; i < nelems; i++) { - if ((sensor = ipmi_sdr_lookup_full_sensor(hdl, entity_refs[i])) - != NULL) { + if ((sdr = ipmi_sdr_lookup_precise(hdl, entity_refs[i], + (uint8_t)e_id, (uint8_t)e_inst)) != NULL) { found_sdr = B_TRUE; break; } else @@ -476,19 +504,30 @@ ipmi_sensor_reading(topo_mod_t *mod, tnode_t *node, topo_version_t vers, topo_mod_ipmi_rele(mod); return (-1); } + switch (sdr->is_type) { + case IPMI_SDR_TYPE_FULL_SENSOR: + fsensor = (ipmi_sdr_full_sensor_t *)sdr->is_record; + sensor_num = fsensor->is_fs_number; + break; + default: + topo_mod_dprintf(mod, "%s does not refer to a full " + "sensor SDR\n", entity_refs[i]); + topo_mod_ipmi_rele(mod); + strarr_free(mod, entity_refs, nelems); + return (-1); + } - if ((reading = ipmi_get_sensor_reading(hdl, sensor->is_fs_number)) - == NULL) { + if ((reading = ipmi_get_sensor_reading(hdl, sensor_num)) == NULL) { topo_mod_dprintf(mod, "Failed to get sensor reading for sensor " "%s, sensor_num=%d (%s)\n", entity_refs[i], - sensor->is_fs_number, ipmi_errmsg(hdl)); + sensor_num, ipmi_errmsg(hdl)); strarr_free(mod, entity_refs, nelems); topo_mod_ipmi_rele(mod); return (-1); } topo_mod_ipmi_rele(mod); - if (ipmi_sdr_conv_reading(sensor, reading->isr_reading, &conv_reading) + if (ipmi_sdr_conv_reading(fsensor, reading->isr_reading, &conv_reading) != 0) { topo_mod_dprintf(mod, "Failed to convert sensor reading for " "sensor %s (%s)\n", entity_refs[i], ipmi_errmsg(hdl)); diff --git a/usr/src/lib/libipmi/common/ipmi_sdr.c b/usr/src/lib/libipmi/common/ipmi_sdr.c index 2adab34f6c..14a5fbd8cc 100644 --- a/usr/src/lib/libipmi/common/ipmi_sdr.c +++ b/usr/src/lib/libipmi/common/ipmi_sdr.c @@ -23,6 +23,10 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright (c) 2018, Joyent, Inc. + */ + #include <libipmi.h> #include <stddef.h> @@ -83,6 +87,8 @@ typedef struct ipmi_sdr_cache_ent { char *isc_name; + uint8_t isc_entity_id; + uint8_t isc_entity_inst; struct ipmi_sdr *isc_sdr; ipmi_hash_link_t isc_link; } ipmi_sdr_cache_ent_t; @@ -184,7 +190,7 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) ipmi_sdr_t *sdr; ipmi_sdr_cache_ent_t *ent; size_t namelen; - uint8_t type; + uint8_t type, e_id = 0, e_inst = 0; char *name; ipmi_sdr_info_t *sip; uint32_t isi_add_ts, isi_erase_ts; @@ -223,6 +229,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = glp->is_gl_idlen; type = glp->is_gl_idtype; name = glp->is_gl_idstring; + e_id = glp->is_gl_entity; + e_inst = glp->is_gl_instance; break; } @@ -234,6 +242,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = flp->is_fl_idlen; name = flp->is_fl_idstring; type = flp->is_fl_idtype; + e_id = flp->is_fl_entity; + e_inst = flp->is_fl_instance; break; } @@ -247,6 +257,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = csp->is_cs_idlen; type = csp->is_cs_idtype; name = csp->is_cs_idstring; + e_id = csp->is_cs_entity_id; + e_inst = csp->is_cs_entity_instance; tmp = LE_IN16(&csp->is_cs_assert_mask); (void) memcpy(&csp->is_cs_assert_mask, &tmp, @@ -272,6 +284,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = fsp->is_fs_idlen; type = fsp->is_fs_idtype; name = fsp->is_fs_idstring; + e_id = fsp->is_fs_entity_id; + e_inst = fsp->is_fs_entity_instance; tmp = LE_IN16(&fsp->is_fs_assert_mask); (void) memcpy(&fsp->is_fs_assert_mask, &tmp, @@ -295,6 +309,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = esp->is_eo_idlen; type = esp->is_eo_idtype; name = esp->is_eo_idstring; + e_id = esp->is_eo_entity_id; + e_inst = esp->is_eo_entity_instance; break; } @@ -306,6 +322,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) namelen = msp->is_ml_idlen; type = msp->is_ml_idtype; name = msp->is_ml_idstring; + e_id = msp->is_ml_entity_id; + e_inst = msp->is_ml_entity_instance; break; } @@ -334,6 +352,8 @@ ipmi_sdr_refresh(ipmi_handle_t *ihp) } ent->isc_sdr = sdr; + ent->isc_entity_id = e_id; + ent->isc_entity_inst = e_inst; if (name != NULL) { if ((ent->isc_name = ipmi_alloc(ihp, namelen + 1)) == @@ -407,18 +427,17 @@ ipmi_sdr_hash_compare(const void *a, const void *b) return (-1); /* - * While it is strange for a service processor to report multiple - * entries with the same name, we allow it by treating the (name, id) - * as the unique identifier. When looking up by name, the SDR pointer - * is NULL, and we return the first matching name. + * When looking up only by name we return the first matching name. For + * a more precise match, callers can optionally specify an IPMI entity + * ID and instance that must also match. */ - if (ap->isc_sdr == NULL || bp->isc_sdr == NULL) - return (0); - - if (ap->isc_sdr->is_id == bp->isc_sdr->is_id) - return (0); - else - return (-1); + if (ap->isc_entity_id != IPMI_ET_UNSPECIFIED && + bp->isc_entity_id != IPMI_ET_UNSPECIFIED) { + if (ap->isc_entity_id != bp->isc_entity_id || + ap->isc_entity_inst != bp->isc_entity_inst) + return (-1); + } + return (0); } int @@ -564,6 +583,13 @@ ipmi_sdr_iter(ipmi_handle_t *ihp, int (*func)(ipmi_handle_t *, ipmi_sdr_t * ipmi_sdr_lookup(ipmi_handle_t *ihp, const char *idstr) { + return (ipmi_sdr_lookup_precise(ihp, idstr, IPMI_ET_UNSPECIFIED, 0)); +} + +ipmi_sdr_t * +ipmi_sdr_lookup_precise(ipmi_handle_t *ihp, const char *idstr, uint8_t e_id, + uint8_t e_inst) +{ ipmi_sdr_cache_ent_t *ent, search; if (ipmi_hash_first(ihp->ih_sdr_cache) == NULL && @@ -572,6 +598,8 @@ ipmi_sdr_lookup(ipmi_handle_t *ihp, const char *idstr) search.isc_name = (char *)idstr; search.isc_sdr = NULL; + search.isc_entity_id = e_id; + search.isc_entity_inst = e_inst; if ((ent = ipmi_hash_lookup(ihp->ih_sdr_cache, &search)) == NULL) { (void) ipmi_set_error(ihp, EIPMI_NOT_PRESENT, NULL); return (NULL); diff --git a/usr/src/lib/libipmi/common/libipmi.h b/usr/src/lib/libipmi/common/libipmi.h index 84573d2711..c3605616ed 100644 --- a/usr/src/lib/libipmi/common/libipmi.h +++ b/usr/src/lib/libipmi/common/libipmi.h @@ -1534,10 +1534,13 @@ extern int ipmi_sdr_iter(ipmi_handle_t *, int (*)(ipmi_handle_t *, const char *, ipmi_sdr_t *, void *), void *); /* - * Lookup the given sensor type by name. These functions automatically read in - * and cache the complete SDR repository. + * Lookup the given sensor type by name or a combination of name and entity + * ID/instance. These functions automatically read in and cache the complete + * SDR repository. */ extern ipmi_sdr_t *ipmi_sdr_lookup(ipmi_handle_t *, const char *); +extern ipmi_sdr_t *ipmi_sdr_lookup_precise(ipmi_handle_t *, const char *, + uint8_t, uint8_t); extern ipmi_sdr_fru_locator_t *ipmi_sdr_lookup_fru(ipmi_handle_t *, const char *); extern ipmi_sdr_generic_locator_t *ipmi_sdr_lookup_generic(ipmi_handle_t *, diff --git a/usr/src/lib/libipmi/common/mapfile-vers b/usr/src/lib/libipmi/common/mapfile-vers index 3852cf83f4..155fcbc471 100644 --- a/usr/src/lib/libipmi/common/mapfile-vers +++ b/usr/src/lib/libipmi/common/mapfile-vers @@ -80,6 +80,7 @@ SYMBOL_VERSION SUNWprivate_1.1 { ipmi_sdr_lookup_full_sensor; ipmi_sdr_lookup_fru; ipmi_sdr_lookup_generic; + ipmi_sdr_lookup_precise; ipmi_sdr_refresh; ipmi_sel_get_entry; ipmi_sel_get_info; diff --git a/usr/src/pkg/manifests/service-fault-management.mf b/usr/src/pkg/manifests/service-fault-management.mf index 4bd1aebf44..081e2f4841 100644 --- a/usr/src/pkg/manifests/service-fault-management.mf +++ b/usr/src/pkg/manifests/service-fault-management.mf @@ -749,6 +749,18 @@ $(i386_ONLY)link \ path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3102-hc-topology.xml \ target=./SSG-2028R-ACR24L-hc-topology.xml $(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3301-hc-topology.xml \ + mode=0444 +$(i386_ONLY)link \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-3302-hc-topology.xml \ + target=./Joyent-Compute-Platform-3301-hc-topology.xml +$(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-330x-chassis-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ + path=usr/platform/i86pc/lib/fm/topo/maps/Joyent-Compute-Platform-330x-fan-hc-topology.xml \ + mode=0444 +$(i386_ONLY)file \ path=usr/platform/i86pc/lib/fm/topo/maps/SSG-2028R-ACR24L-chassis-hc-topology.xml \ mode=0444 $(i386_ONLY)file \ |
