1275c9da8Seschrock /*
2275c9da8Seschrock * CDDL HEADER START
3275c9da8Seschrock *
4275c9da8Seschrock * The contents of this file are subject to the terms of the
5275c9da8Seschrock * Common Development and Distribution License (the "License").
6275c9da8Seschrock * You may not use this file except in compliance with the License.
7275c9da8Seschrock *
8275c9da8Seschrock * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9275c9da8Seschrock * or http://www.opensolaris.org/os/licensing.
10275c9da8Seschrock * See the License for the specific language governing permissions
11275c9da8Seschrock * and limitations under the License.
12275c9da8Seschrock *
13275c9da8Seschrock * When distributing Covered Code, include this CDDL HEADER in each
14275c9da8Seschrock * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15275c9da8Seschrock * If applicable, add the following below this CDDL HEADER, with the
16275c9da8Seschrock * fields enclosed by brackets "[]" replaced with your own identifying
17275c9da8Seschrock * information: Portions Copyright [yyyy] [name of copyright owner]
18275c9da8Seschrock *
19275c9da8Seschrock * CDDL HEADER END
20275c9da8Seschrock */
21275c9da8Seschrock
22275c9da8Seschrock /*
23*ac88567aSHyon Kim * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24275c9da8Seschrock */
25275c9da8Seschrock
26275c9da8Seschrock #include <stddef.h>
27275c9da8Seschrock #include <string.h>
28275c9da8Seschrock #include <strings.h>
29275c9da8Seschrock #include <libnvpair.h>
30275c9da8Seschrock
31275c9da8Seschrock #include <scsi/libses.h>
32275c9da8Seschrock #include <scsi/plugins/ses/framework/ses2_impl.h>
33275c9da8Seschrock
34275c9da8Seschrock static int
enc_parse_sd(ses2_elem_status_impl_t * esip,nvlist_t * nvl)35275c9da8Seschrock enc_parse_sd(ses2_elem_status_impl_t *esip, nvlist_t *nvl)
36275c9da8Seschrock {
37275c9da8Seschrock ses2_enclosure_status_impl_t *sdp;
38275c9da8Seschrock int nverr;
39275c9da8Seschrock
40275c9da8Seschrock sdp = (ses2_enclosure_status_impl_t *)esip;
41275c9da8Seschrock
42275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_PROP_STATUS_CODE,
43275c9da8Seschrock sdp->sesi_common.sesi_status_code);
44275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_SWAP,
45275c9da8Seschrock sdp->sesi_common.sesi_swap);
46275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_DISABLED,
47275c9da8Seschrock sdp->sesi_common.sesi_disabled);
48275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_PRDFAIL,
49275c9da8Seschrock sdp->sesi_common.sesi_prdfail);
50275c9da8Seschrock
51275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_IDENT, sdp->sesi_ident);
52275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN,
53275c9da8Seschrock sdp->sesi_warning_indication);
54275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL,
55275c9da8Seschrock sdp->sesi_failure_indication);
56275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DELAY,
57275c9da8Seschrock sdp->sesi_power_delay);
58275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_WARN_REQ,
59275c9da8Seschrock sdp->sesi_warning_requested);
60275c9da8Seschrock SES_NV_ADD(boolean_value, nverr, nvl, SES_PROP_FAIL_REQ,
61275c9da8Seschrock sdp->sesi_warning_requested);
62275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_POWER_DURATION,
63275c9da8Seschrock sdp->sesi_power_duration);
64275c9da8Seschrock
65275c9da8Seschrock return (0);
66275c9da8Seschrock }
67275c9da8Seschrock
68275c9da8Seschrock static int
enc_parse_help(ses_plugin_t * sp,ses_node_t * np)69275c9da8Seschrock enc_parse_help(ses_plugin_t *sp, ses_node_t *np)
70275c9da8Seschrock {
71275c9da8Seschrock ses_snap_t *snap = ses_node_snapshot(np);
72275c9da8Seschrock ses2_help_page_impl_t *hpip;
73275c9da8Seschrock ses2_subhelp_page_impl_t *shpip;
74275c9da8Seschrock ses2_subhelp_text_impl_t *tip;
75275c9da8Seschrock nvlist_t *nvl = ses_node_props(np);
76275c9da8Seschrock uint64_t eid;
77*ac88567aSHyon Kim size_t len, textlen;
78275c9da8Seschrock off_t pos;
79275c9da8Seschrock int nverr;
80275c9da8Seschrock
81275c9da8Seschrock if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
82275c9da8Seschrock return (0);
83275c9da8Seschrock
84275c9da8Seschrock if ((shpip = ses_plugin_page_lookup(sp, snap,
85275c9da8Seschrock SES2_DIAGPAGE_SUBENCLOSURE_HELP_TEXT, np, &len)) != NULL) {
86275c9da8Seschrock pos = 0;
87275c9da8Seschrock for (tip = (ses2_subhelp_text_impl_t *)shpip->sspi_data;
88275c9da8Seschrock pos < SCSI_READ16(&shpip->sspi_page_length);
89275c9da8Seschrock pos += SES2_SUBHELP_LEN(tip),
90275c9da8Seschrock tip = (ses2_subhelp_text_impl_t *)((uint8_t *)tip + pos)) {
91275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(tip, shpip, len))
92275c9da8Seschrock break;
93275c9da8Seschrock
94275c9da8Seschrock if (tip->ssti_subenclosure_identifier != eid)
95275c9da8Seschrock continue;
96275c9da8Seschrock
97*ac88567aSHyon Kim textlen = SCSI_READ16(
98*ac88567aSHyon Kim &tip->ssti_subenclosure_help_text_length);
99*ac88567aSHyon Kim
100275c9da8Seschrock if (!SES_WITHIN_PAGE(tip->ssti_subenclosure_help_text,
101*ac88567aSHyon Kim textlen, shpip, len))
102275c9da8Seschrock break;
103275c9da8Seschrock
104275c9da8Seschrock SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP,
105*ac88567aSHyon Kim tip->ssti_subenclosure_help_text, textlen);
106275c9da8Seschrock return (0);
107275c9da8Seschrock }
108275c9da8Seschrock }
109275c9da8Seschrock
110275c9da8Seschrock if (eid == 0 && (hpip = ses_plugin_page_lookup(sp, snap,
111275c9da8Seschrock SES2_DIAGPAGE_HELP_TEXT, np, &len)) != NULL) {
112275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(hpip, hpip, len))
113275c9da8Seschrock return (0);
114275c9da8Seschrock
115275c9da8Seschrock if (!SES_WITHIN_PAGE(hpip->shpi_help_text,
116275c9da8Seschrock SCSI_READ16(&hpip->shpi_page_length), hpip, len))
117275c9da8Seschrock return (0);
118275c9da8Seschrock
119275c9da8Seschrock SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_HELP,
120275c9da8Seschrock hpip->shpi_help_text, SCSI_READ16(&hpip->shpi_page_length));
121275c9da8Seschrock }
122275c9da8Seschrock
123275c9da8Seschrock return (0);
124275c9da8Seschrock }
125275c9da8Seschrock
126275c9da8Seschrock static int
enc_parse_string_in(ses_plugin_t * sp,ses_node_t * np)127275c9da8Seschrock enc_parse_string_in(ses_plugin_t *sp, ses_node_t *np)
128275c9da8Seschrock {
129275c9da8Seschrock ses_snap_t *snap = ses_node_snapshot(np);
130275c9da8Seschrock ses2_string_in_page_impl_t *sip;
131275c9da8Seschrock ses2_substring_in_page_impl_t *ssip;
132275c9da8Seschrock ses2_substring_in_data_impl_t *dip;
133275c9da8Seschrock nvlist_t *nvl = ses_node_props(np);
134275c9da8Seschrock uint64_t eid;
135275c9da8Seschrock off_t pos;
136275c9da8Seschrock size_t len, textlen;
137275c9da8Seschrock int nverr;
138275c9da8Seschrock
139275c9da8Seschrock if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
140275c9da8Seschrock return (0);
141275c9da8Seschrock
142275c9da8Seschrock if ((ssip = ses_plugin_page_lookup(sp, snap,
143275c9da8Seschrock SES2_DIAGPAGE_SUBENCLOSURE_STRING_IO, np, &len)) != NULL) {
144275c9da8Seschrock pos = 0;
145275c9da8Seschrock for (dip = (ses2_substring_in_data_impl_t *)ssip->ssipi_data;
146275c9da8Seschrock pos < SCSI_READ16(&ssip->ssipi_page_length);
147275c9da8Seschrock pos += SES2_SUBSTR_LEN(dip),
148275c9da8Seschrock dip = (ses2_substring_in_data_impl_t *)
149275c9da8Seschrock ((uint8_t *)dip + pos)) {
150275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(dip, ssip, len))
151275c9da8Seschrock break;
152275c9da8Seschrock
153275c9da8Seschrock if (dip->ssidi_subenclosure_identifier != eid)
154275c9da8Seschrock continue;
155275c9da8Seschrock
156*ac88567aSHyon Kim textlen =
157*ac88567aSHyon Kim SCSI_READ16(&dip->ssidi_substring_data_length);
158*ac88567aSHyon Kim
159*ac88567aSHyon Kim if (!SES_WITHIN_PAGE(dip->ssidi_data, textlen,
160*ac88567aSHyon Kim ssip, len))
161275c9da8Seschrock break;
162275c9da8Seschrock
163275c9da8Seschrock SES_NV_ADD(fixed_string, nverr, nvl, SES_EN_PROP_STRING,
164*ac88567aSHyon Kim (char *)dip->ssidi_data, textlen);
165275c9da8Seschrock return (0);
166275c9da8Seschrock }
167275c9da8Seschrock }
168275c9da8Seschrock
169275c9da8Seschrock if (eid == 0 && (sip = ses_plugin_page_lookup(sp, snap,
170275c9da8Seschrock SES2_DIAGPAGE_STRING_IO, np, &len)) != NULL) {
171275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(sip, sip, len))
172275c9da8Seschrock return (0);
173275c9da8Seschrock
174275c9da8Seschrock textlen = SCSI_READ16(&sip->ssipi_page_length);
175275c9da8Seschrock
176275c9da8Seschrock if (!SES_WITHIN_PAGE(sip->ssipi_data, textlen, sip, len))
177275c9da8Seschrock return (0);
178275c9da8Seschrock
179275c9da8Seschrock SES_NV_ADD(byte_array, nverr, nvl, SES_EN_PROP_STRING,
180275c9da8Seschrock sip->ssipi_data, textlen);
181275c9da8Seschrock }
182275c9da8Seschrock
183275c9da8Seschrock return (0);
184275c9da8Seschrock }
185275c9da8Seschrock
186275c9da8Seschrock static int
enc_parse_descr(ses_plugin_t * sp,ses_node_t * np)187275c9da8Seschrock enc_parse_descr(ses_plugin_t *sp, ses_node_t *np)
188275c9da8Seschrock {
189275c9da8Seschrock char *desc;
190275c9da8Seschrock nvlist_t *props = ses_node_props(np);
191275c9da8Seschrock int nverr;
192275c9da8Seschrock size_t len;
193275c9da8Seschrock
194275c9da8Seschrock if ((desc = ses_plugin_page_lookup(sp, ses_node_snapshot(np),
195275c9da8Seschrock SES2_DIAGPAGE_ELEMENT_DESC, np, &len)) == NULL)
196275c9da8Seschrock return (0);
197275c9da8Seschrock
198275c9da8Seschrock SES_NV_ADD(fixed_string, nverr, props, SES_PROP_DESCRIPTION,
199275c9da8Seschrock desc, len);
200275c9da8Seschrock
201275c9da8Seschrock return (0);
202275c9da8Seschrock }
203275c9da8Seschrock
204275c9da8Seschrock static int
enc_parse_dlucode(ses_plugin_t * sp,ses_node_t * np)205275c9da8Seschrock enc_parse_dlucode(ses_plugin_t *sp, ses_node_t *np)
206275c9da8Seschrock {
207275c9da8Seschrock ses_snap_t *snap = ses_node_snapshot(np);
208275c9da8Seschrock ses2_ucode_status_page_impl_t *upip;
209275c9da8Seschrock ses2_ucode_status_descr_impl_t *dip;
210275c9da8Seschrock nvlist_t *nvl = ses_node_props(np);
211275c9da8Seschrock int nverr, i;
212275c9da8Seschrock size_t len;
213275c9da8Seschrock uint64_t eid;
214275c9da8Seschrock
215275c9da8Seschrock if ((upip = ses_plugin_page_lookup(sp, snap,
216275c9da8Seschrock SES2_DIAGPAGE_DL_MICROCODE_CTL_STATUS, np, &len)) == NULL)
217275c9da8Seschrock return (0);
218275c9da8Seschrock
219275c9da8Seschrock if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
220275c9da8Seschrock return (0);
221275c9da8Seschrock
222275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(upip, upip, len))
223275c9da8Seschrock return (0);
224275c9da8Seschrock
225275c9da8Seschrock /*
226275c9da8Seschrock * The number of subenclosures excludes the primary subenclosure, which
227275c9da8Seschrock * is always part of the response.
228275c9da8Seschrock */
229275c9da8Seschrock for (dip = &upip->suspi_descriptors[0], i = 0;
230275c9da8Seschrock i <= upip->suspi_n_subenclosures;
231275c9da8Seschrock i++, dip++) {
232275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(dip, upip, len))
233275c9da8Seschrock break;
234275c9da8Seschrock
235275c9da8Seschrock if (dip->susdi_subenclosure_identifier != eid)
236275c9da8Seschrock continue;
237275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE,
238275c9da8Seschrock dip->susdi_subenclosure_dl_status);
239275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_A,
240275c9da8Seschrock dip->susdi_subenclosure_dl_addl_status);
241275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_SZ,
242275c9da8Seschrock SCSI_READ32(&dip->susdi_subenclosure_dl_max_size));
243275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_BUF,
244275c9da8Seschrock dip->susdi_subenclosure_dl_buffer_id);
245275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_UCODE_OFF,
246275c9da8Seschrock dip->susdi_subenclosure_dl_buffer_offset);
247275c9da8Seschrock break;
248275c9da8Seschrock }
249275c9da8Seschrock
250275c9da8Seschrock return (0);
251275c9da8Seschrock }
252275c9da8Seschrock
253275c9da8Seschrock static int
enc_parse_subnick(ses_plugin_t * sp,ses_node_t * np)254275c9da8Seschrock enc_parse_subnick(ses_plugin_t *sp, ses_node_t *np)
255275c9da8Seschrock {
256275c9da8Seschrock ses_snap_t *snap = ses_node_snapshot(np);
257275c9da8Seschrock ses2_subnick_status_page_impl_t *spip;
258275c9da8Seschrock ses2_subnick_descr_impl_t *dip;
259275c9da8Seschrock nvlist_t *nvl = ses_node_props(np);
260275c9da8Seschrock int nverr, i;
261275c9da8Seschrock size_t len;
262275c9da8Seschrock uint64_t eid;
263275c9da8Seschrock
264275c9da8Seschrock if (nvlist_lookup_uint64(nvl, SES_EN_PROP_EID, &eid) != 0)
265275c9da8Seschrock return (0);
266275c9da8Seschrock
267275c9da8Seschrock if ((spip = ses_plugin_page_lookup(sp, snap,
268275c9da8Seschrock SES2_DIAGPAGE_SUBENCLOSURE_NICKNAME_CTL_STATUS,
269275c9da8Seschrock np, &len)) == NULL)
270275c9da8Seschrock return (0);
271275c9da8Seschrock
272275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(spip, spip, len))
273275c9da8Seschrock return (0);
274275c9da8Seschrock
275275c9da8Seschrock for (dip = &spip->sspci_subnicks[0], i = 0;
27651ece835Seschrock i <= spip->sspci_n_subenclosures;
277275c9da8Seschrock i++, dip++) {
278275c9da8Seschrock if (!SES_WITHIN_PAGE_STRUCT(dip, spip, len))
279275c9da8Seschrock break;
280275c9da8Seschrock
281275c9da8Seschrock if (dip->ssdi_subenclosure_identifier != eid)
282275c9da8Seschrock continue;
283275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_STATUS,
284275c9da8Seschrock dip->ssdi_subenclosure_nick_status);
285275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_ADDL_STATUS,
286275c9da8Seschrock dip->ssdi_subenclosure_nick_addl_status);
287275c9da8Seschrock SES_NV_ADD_FS(nverr, nvl, SES_EN_PROP_NICK,
288275c9da8Seschrock dip->ssdi_subenclosure_nickname);
289275c9da8Seschrock SES_NV_ADD(uint64, nverr, nvl, SES_EN_PROP_NICK_LANG,
290275c9da8Seschrock dip->ssdi_subenclosure_nick_lang_code);
291275c9da8Seschrock break;
292275c9da8Seschrock }
293275c9da8Seschrock
294275c9da8Seschrock return (0);
295275c9da8Seschrock }
296275c9da8Seschrock
297275c9da8Seschrock int
ses2_fill_enclosure_node(ses_plugin_t * sp,ses_node_t * np)298275c9da8Seschrock ses2_fill_enclosure_node(ses_plugin_t *sp, ses_node_t *np)
299275c9da8Seschrock {
300275c9da8Seschrock ses_snap_t *snap = ses_node_snapshot(np);
301275c9da8Seschrock nvlist_t *props = ses_node_props(np);
302275c9da8Seschrock ses2_elem_status_impl_t *esip;
303275c9da8Seschrock int err;
304275c9da8Seschrock size_t len;
305275c9da8Seschrock
306275c9da8Seschrock if ((esip = ses_plugin_page_lookup(sp, snap,
307275c9da8Seschrock SES2_DIAGPAGE_ENCLOSURE_CTL_STATUS, np, &len)) != NULL) {
308275c9da8Seschrock if ((err = enc_parse_sd(esip, props)) != 0)
309275c9da8Seschrock return (err);
310275c9da8Seschrock }
311275c9da8Seschrock
312275c9da8Seschrock if ((err = enc_parse_help(sp, np)) != 0)
313275c9da8Seschrock return (err);
314275c9da8Seschrock
315275c9da8Seschrock if ((err = enc_parse_string_in(sp, np)) != 0)
316275c9da8Seschrock return (err);
317275c9da8Seschrock
318275c9da8Seschrock if ((err = enc_parse_descr(sp, np)) != 0)
319275c9da8Seschrock return (err);
320275c9da8Seschrock
321275c9da8Seschrock if ((err = enc_parse_dlucode(sp, np)) != 0)
322275c9da8Seschrock return (err);
323275c9da8Seschrock
324275c9da8Seschrock if ((err = enc_parse_subnick(sp, np)) != 0)
325275c9da8Seschrock return (err);
326275c9da8Seschrock
327275c9da8Seschrock return (0);
328275c9da8Seschrock }
329