1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <stddef.h> 30 #include <string.h> 31 #include <strings.h> 32 #include <libnvpair.h> 33 34 #include <scsi/libses.h> 35 #include <scsi/plugins/ses/framework/ses2_impl.h> 36 37 static int 38 enc_parse_sd(ses2_elem_status_impl_t *esip, nvlist_t *nvl) 39 { 40 ses2_enclosure_status_impl_t *sdp; 41 int nverr; 42 43 sdp = (ses2_enclosure_status_impl_t *)esip; 44 45 SES_NV_ADD(uint64, nverr, nvl, SES_PROP_STATUS_CODE, 46 sdp->sesi_common.sesi_status_code); 47 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_SWAP, 48 sdp->sesi_common.sesi_swap); 49 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED, 50 sdp->sesi_common.sesi_disabled); 51 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_PRDFAIL, 52 sdp->sesi_common.sesi_prdfail); 53 54 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sdp->sesi_ident); 55 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN, 56 sdp->sesi_warning_indication); 57 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL, 58 sdp->sesi_failure_indication); 59 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DELAY, 60 sdp->sesi_power_delay); 61 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_REQ, 62 sdp->sesi_warning_requested); 63 SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL_REQ, 64 sdp->sesi_warning_requested); 65 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DURATION, 66 sdp->sesi_power_duration); 67 68 return (0); 69 } 70 71 static int 72 enc_parse_help(ses_plugin_t *sp, ses_node_t *np) 73 { 74 ses_snap_t *snap = ses_node_snapshot(np); 75 ses2_help_page_impl_t *hpip; 76 ses2_subhelp_page_impl_t *shpip; 77 ses2_subhelp_text_impl_t *tip; 78 nvlist_t *nvl = ses_node_props(np); 79 uint64_t eid; 80 size_t len; 81 off_t pos; 82 int nverr; 83 84 if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0) 85 return (0); 86 87 if ((shpip = ses_plugin_page_lookup(sp, snap, 88 SES2_DIAGPAGE_SUBENCLOSURE_HELP_TEXT, np, &len)) != NULL) { 89 pos = 0; 90 for (tip = (ses2_subhelp_text_impl_t *)shpip->sspi_data; 91 pos < SCSI_READ16(&shpip->sspi_page_length); 92 pos += SES2_SUBHELP_LEN(tip), 93 tip = (ses2_subhelp_text_impl_t *)((uint8_t *)tip + pos)) { 94 if (!SES_WITHIN_PAGE_STRUCT(tip, shpip, len)) 95 break; 96 97 if (tip->ssti_subenclosure_identifier != eid) 98 continue; 99 100 if (!SES_WITHIN_PAGE(tip->ssti_subenclosure_help_text, 101 tip->ssti_subenclosure_help_text_length, shpip, 102 len)) 103 break; 104 105 SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP, 106 tip->ssti_subenclosure_help_text, 107 tip->ssti_subenclosure_help_text_length); 108 return (0); 109 } 110 } 111 112 if (eid == 0 && (hpip = ses_plugin_page_lookup(sp, snap, 113 SES2_DIAGPAGE_HELP_TEXT, np, &len)) != NULL) { 114 if (!SES_WITHIN_PAGE_STRUCT(hpip, hpip, len)) 115 return (0); 116 117 if (!SES_WITHIN_PAGE(hpip->shpi_help_text, 118 SCSI_READ16(&hpip->shpi_page_length), hpip, len)) 119 return (0); 120 121 SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP, 122 hpip->shpi_help_text, SCSI_READ16(&hpip->shpi_page_length)); 123 } 124 125 return (0); 126 } 127 128 static int 129 enc_parse_string_in(ses_plugin_t *sp, ses_node_t *np) 130 { 131 ses_snap_t *snap = ses_node_snapshot(np); 132 ses2_string_in_page_impl_t *sip; 133 ses2_substring_in_page_impl_t *ssip; 134 ses2_substring_in_data_impl_t *dip; 135 nvlist_t *nvl = ses_node_props(np); 136 uint64_t eid; 137 off_t pos; 138 size_t len, textlen; 139 int nverr; 140 141 if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0) 142 return (0); 143 144 if ((ssip = ses_plugin_page_lookup(sp, snap, 145 SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO, np, &len)) != NULL) { 146 pos = 0; 147 for (dip = (ses2_substring_in_data_impl_t *)ssip->ssipi_data; 148 pos < SCSI_READ16(&ssip->ssipi_page_length); 149 pos += SES2_SUBSTR_LEN(dip), 150 dip = (ses2_substring_in_data_impl_t *) 151 ((uint8_t *)dip + pos)) { 152 if (!SES_WITHIN_PAGE_STRUCT(dip, ssip, len)) 153 break; 154 155 if (dip->ssidi_subenclosure_identifier != eid) 156 continue; 157 158 if (!SES_WITHIN_PAGE(dip->ssidi_data, 159 dip->ssidi_substring_data_length, ssip, len)) 160 break; 161 162 SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_STRING, 163 (char *)dip->ssidi_data, 164 dip->ssidi_substring_data_length); 165 return (0); 166 } 167 } 168 169 if (eid == 0 && (sip = ses_plugin_page_lookup(sp, snap, 170 SES2_DIAGPAGE_STRING_IO, np, &len)) != NULL) { 171 if (!SES_WITHIN_PAGE_STRUCT(sip, sip, len)) 172 return (0); 173 174 textlen = SCSI_READ16(&sip->ssipi_page_length); 175 176 if (!SES_WITHIN_PAGE(sip->ssipi_data, textlen, sip, len)) 177 return (0); 178 179 SES_NV_ADD(byte_array, nverr, nvl, SES_EN_PROP_STRING, 180 sip->ssipi_data, textlen); 181 } 182 183 return (0); 184 } 185 186 static int 187 enc_parse_descr(ses_plugin_t *sp, ses_node_t *np) 188 { 189 char *desc; 190 nvlist_t *props = ses_node_props(np); 191 int nverr; 192 size_t len; 193 194 if ((desc = ses_plugin_page_lookup(sp, ses_node_snapshot(np), 195 SES2_DIAGPAGE_ELEMENT_DESC, np, &len)) == NULL) 196 return (0); 197 198 SES_NV_ADD(fixed_string, nverr, props, SES_PROP_DESCRIPTION, 199 desc, len); 200 201 return (0); 202 } 203 204 static int 205 enc_parse_dlucode(ses_plugin_t *sp, ses_node_t *np) 206 { 207 ses_snap_t *snap = ses_node_snapshot(np); 208 ses2_ucode_status_page_impl_t *upip; 209 ses2_ucode_status_descr_impl_t *dip; 210 nvlist_t *nvl = ses_node_props(np); 211 int nverr, i; 212 size_t len; 213 uint64_t eid; 214 215 if ((upip = ses_plugin_page_lookup(sp, snap, 216 SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS, np, &len)) == NULL) 217 return (0); 218 219 if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0) 220 return (0); 221 222 if (!SES_WITHIN_PAGE_STRUCT(upip, upip, len)) 223 return (0); 224 225 /* 226 * The number of subenclosures excludes the primary subenclosure, which 227 * is always part of the response. 228 */ 229 for (dip = &upip->suspi_descriptors[0], i = 0; 230 i <= upip->suspi_n_subenclosures; 231 i++, dip++) { 232 if (!SES_WITHIN_PAGE_STRUCT(dip, upip, len)) 233 break; 234 235 if (dip->susdi_subenclosure_identifier != eid) 236 continue; 237 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE, 238 dip->susdi_subenclosure_dl_status); 239 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_A, 240 dip->susdi_subenclosure_dl_addl_status); 241 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_SZ, 242 SCSI_READ32(&dip->susdi_subenclosure_dl_max_size)); 243 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_BUF, 244 dip->susdi_subenclosure_dl_buffer_id); 245 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_OFF, 246 dip->susdi_subenclosure_dl_buffer_offset); 247 break; 248 } 249 250 return (0); 251 } 252 253 static int 254 enc_parse_subnick(ses_plugin_t *sp, ses_node_t *np) 255 { 256 ses_snap_t *snap = ses_node_snapshot(np); 257 ses2_subnick_status_page_impl_t *spip; 258 ses2_subnick_descr_impl_t *dip; 259 nvlist_t *nvl = ses_node_props(np); 260 int nverr, i; 261 size_t len; 262 uint64_t eid; 263 264 if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0) 265 return (0); 266 267 if ((spip = ses_plugin_page_lookup(sp, snap, 268 SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS, 269 np, &len)) == NULL) 270 return (0); 271 272 if (!SES_WITHIN_PAGE_STRUCT(spip, spip, len)) 273 return (0); 274 275 for (dip = &spip->sspci_subnicks[0], i = 0; 276 i <= spip->sspci_n_subenclosures; 277 i++, dip++) { 278 if (!SES_WITHIN_PAGE_STRUCT(dip, spip, len)) 279 break; 280 281 if (dip->ssdi_subenclosure_identifier != eid) 282 continue; 283 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_STATUS, 284 dip->ssdi_subenclosure_nick_status); 285 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_ADDL_STATUS, 286 dip->ssdi_subenclosure_nick_addl_status); 287 SES_NV_ADD_FS(nverr, nvl, SES_EN_PROP_NICK, 288 dip->ssdi_subenclosure_nickname); 289 SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_LANG, 290 dip->ssdi_subenclosure_nick_lang_code); 291 break; 292 } 293 294 return (0); 295 } 296 297 int 298 ses2_fill_enclosure_node(ses_plugin_t *sp, ses_node_t *np) 299 { 300 ses_snap_t *snap = ses_node_snapshot(np); 301 nvlist_t *props = ses_node_props(np); 302 ses2_elem_status_impl_t *esip; 303 int err; 304 size_t len; 305 306 if ((esip = ses_plugin_page_lookup(sp, snap, 307 SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, np, &len)) != NULL) { 308 if ((err = enc_parse_sd(esip, props)) != 0) 309 return (err); 310 } 311 312 if ((err = enc_parse_help(sp, np)) != 0) 313 return (err); 314 315 if ((err = enc_parse_string_in(sp, np)) != 0) 316 return (err); 317 318 if ((err = enc_parse_descr(sp, np)) != 0) 319 return (err); 320 321 if ((err = enc_parse_dlucode(sp, np)) != 0) 322 return (err); 323 324 if ((err = enc_parse_subnick(sp, np)) != 0) 325 return (err); 326 327 return (0); 328 } 329