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 2010 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*
28 * String conversion routine for hardware capabilities types.
29 */
30#include	<strings.h>
31#include	<stdio.h>
32#include	<elfcap.h>
33#include	"cap_msg.h"
34#include	"_conv.h"
35
36const conv_ds_t **
37conv_cap_tag_strings(Conv_fmt_flags_t fmt_flags)
38{
39#if	(CA_SUNW_NUM != (CA_SUNW_ID + 1))
40#error	"CA_SUNW_NUM has grown"
41#endif
42	static const Msg	tags_cf[] = {
43		MSG_CA_SUNW_NULL_CF,	MSG_CA_SUNW_HW_1_CF,
44		MSG_CA_SUNW_SF_1_CF,	MSG_CA_SUNW_HW_2_CF,
45		MSG_CA_SUNW_PLAT_CF,	MSG_CA_SUNW_MACH_CF,
46		MSG_CA_SUNW_ID_CF
47	};
48	static const Msg	tags_nf[] = {
49		MSG_CA_SUNW_NULL_NF,	MSG_CA_SUNW_HW_1_NF,
50		MSG_CA_SUNW_SF_1_NF,	MSG_CA_SUNW_HW_2_NF,
51		MSG_CA_SUNW_PLAT_NF,	MSG_CA_SUNW_MACH_NF,
52		MSG_CA_SUNW_ID_NF
53	};
54	static const conv_ds_msg_t ds_tags_cf = {
55	    CONV_DS_MSG_INIT(ELFCLASSNONE, tags_cf) };
56	static const conv_ds_msg_t ds_tags_nf = {
57	    CONV_DS_MSG_INIT(ELFCLASSNONE, tags_nf) };
58
59	static const conv_ds_t *ds_cf[] = { CONV_DS_ADDR(ds_tags_cf), NULL };
60	static const conv_ds_t *ds_nf[] = { CONV_DS_ADDR(ds_tags_nf), NULL };
61
62
63	return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
64	    ds_nf : ds_cf);
65}
66
67conv_iter_ret_t
68conv_iter_cap_tags(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
69    void *uvalue)
70{
71	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
72	    conv_cap_tag_strings(fmt_flags), func, uvalue));
73}
74
75/*
76 * Given an array of elfcap_desc_t, and a count, call the specified
77 * iteration for each value in the array.
78 */
79static conv_iter_ret_t
80conv_iter_elfcap(const elfcap_desc_t *cdp, uint_t cnum,
81    Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue)
82{
83	const char	*str;
84
85	fmt_flags = CONV_TYPE_FMT_ALT(fmt_flags);
86
87	for (; cnum-- > 0; cdp++) {
88		/*
89		 * Skip "reserved" bits. These are unassigned bits in the
90		 * middle of the assigned range.
91		 */
92		if (cdp->c_val == 0)
93			continue;
94
95		switch (fmt_flags) {
96		default:
97			str = cdp->c_full.s_str;
98			break;
99		case CONV_FMT_ALT_CFNP:
100			str = cdp->c_uc.s_str;
101			break;
102		case CONV_FMT_ALT_NF:
103			str = cdp->c_lc.s_str;
104			break;
105		}
106
107		if ((* func)(str, cdp->c_val, uvalue) == CONV_ITER_DONE)
108			return (CONV_ITER_DONE);
109	}
110
111	return (CONV_ITER_CONT);
112}
113
114/*
115 * Iterate the strings for CA_SUNW_HW.
116 */
117conv_iter_ret_t
118conv_iter_cap_val_hw1(Half mach, Conv_fmt_flags_t fmt_flags,
119    conv_iter_cb_t func, void *uvalue)
120{
121	if ((mach == EM_386) || (mach == EM_486) ||
122	    (mach == EM_AMD64) || (mach == CONV_MACH_ALL))
123		if (conv_iter_elfcap(elfcap_getdesc_hw1_386(),
124		    ELFCAP_NUM_HW1_386, fmt_flags, func, uvalue) ==
125		    CONV_ITER_DONE)
126			return (CONV_ITER_DONE);
127
128	if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
129	    (mach == EM_SPARCV9) || (mach == CONV_MACH_ALL))
130		if (conv_iter_elfcap(elfcap_getdesc_hw1_sparc(),
131		    ELFCAP_NUM_HW1_SPARC, fmt_flags, func, uvalue) ==
132		    CONV_ITER_DONE)
133			return (CONV_ITER_DONE);
134
135	return (CONV_ITER_CONT);
136}
137
138conv_iter_ret_t
139/* ARGSUSED0 */
140conv_iter_cap_val_hw2(Half mach, Conv_fmt_flags_t fmt_flags,
141    conv_iter_cb_t func, void *uvalue)
142{
143	return (CONV_ITER_DONE);
144}
145
146/*
147 * Iterate the strings for CA_SUNW_SF1
148 */
149conv_iter_ret_t
150conv_iter_cap_val_sf1(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
151    void *uvalue)
152{
153	return (conv_iter_elfcap(elfcap_getdesc_sf1(), ELFCAP_NUM_SF1,
154	    fmt_flags, func, uvalue));
155}
156