xref: /illumos-gate/usr/src/cmd/sgs/libconv/common/cap.c (revision 08278a5e)
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 
36 const conv_ds_t **
conv_cap_tag_strings(Conv_fmt_flags_t fmt_flags)37 conv_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 
67 conv_iter_ret_t
conv_iter_cap_tags(Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)68 conv_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  */
79 static conv_iter_ret_t
conv_iter_elfcap(const elfcap_desc_t * cdp,uint_t cnum,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)80 conv_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  */
117 conv_iter_ret_t
conv_iter_cap_val_hw1(Half mach,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)118 conv_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 
138 conv_iter_ret_t
139 /* ARGSUSED0 */
conv_iter_cap_val_hw2(Half mach,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)140 conv_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  */
149 conv_iter_ret_t
conv_iter_cap_val_sf1(Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)150 conv_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