xref: /illumos-gate/usr/src/cmd/sgs/libconv/common/cap.c (revision 56726c7e)
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  * Copyright 2022 Oxide Computer Company
27  */
28 
29 /*
30  * String conversion routine for hardware capabilities types.
31  */
32 #include	<strings.h>
33 #include	<stdio.h>
34 #include	<elfcap.h>
35 #include	"cap_msg.h"
36 #include	"_conv.h"
37 
38 /*
39  * These are assertions that the various sizes that are dependent on elfcap.c
40  * are actually all the same.
41  */
42 #if CONV_CAP_VAL_HW1_BUFSIZE != ELFCAP_HW1_BUFSIZE
43 #error "libconv needs to update CONV_CAP_VAL_HW1_BUFSIZE to match elfcap.h"
44 #endif
45 
46 #if CONV_CAP_VAL_HW2_BUFSIZE != ELFCAP_HW2_BUFSIZE
47 #error "libconv needs to update CONV_CAP_VAL_HW2_BUFSIZE to match elfcap.h"
48 #endif
49 
50 #if CONV_CAP_VAL_HW3_BUFSIZE != ELFCAP_HW3_BUFSIZE
51 #error "libconv needs to update CONV_CAP_VAL_HW3_BUFSIZE to match elfcap.h"
52 #endif
53 
54 #if CONV_CAP_VAL_SF1_BUFSIZE != ELFCAP_SF1_BUFSIZE
55 #error "libconv needs to update CONV_CAP_VAL_SF1_BUFSIZE to match elfcap.h"
56 #endif
57 
58 const conv_ds_t **
conv_cap_tag_strings(Conv_fmt_flags_t fmt_flags)59 conv_cap_tag_strings(Conv_fmt_flags_t fmt_flags)
60 {
61 #if	(CA_SUNW_NUM != (CA_SUNW_HW_3 + 1))
62 #error	"CA_SUNW_NUM has grown"
63 #endif
64 	static const Msg	tags_cf[] = {
65 		MSG_CA_SUNW_NULL_CF,	MSG_CA_SUNW_HW_1_CF,
66 		MSG_CA_SUNW_SF_1_CF,	MSG_CA_SUNW_HW_2_CF,
67 		MSG_CA_SUNW_PLAT_CF,	MSG_CA_SUNW_MACH_CF,
68 		MSG_CA_SUNW_ID_CF,	MSG_CA_SUNW_HW_3_CF
69 	};
70 	static const Msg	tags_nf[] = {
71 		MSG_CA_SUNW_NULL_NF,	MSG_CA_SUNW_HW_1_NF,
72 		MSG_CA_SUNW_SF_1_NF,	MSG_CA_SUNW_HW_2_NF,
73 		MSG_CA_SUNW_PLAT_NF,	MSG_CA_SUNW_MACH_NF,
74 		MSG_CA_SUNW_ID_NF,	MSG_CA_SUNW_HW_3_NF
75 	};
76 	static const conv_ds_msg_t ds_tags_cf = {
77 	    CONV_DS_MSG_INIT(ELFCLASSNONE, tags_cf) };
78 	static const conv_ds_msg_t ds_tags_nf = {
79 	    CONV_DS_MSG_INIT(ELFCLASSNONE, tags_nf) };
80 
81 	static const conv_ds_t *ds_cf[] = { CONV_DS_ADDR(ds_tags_cf), NULL };
82 	static const conv_ds_t *ds_nf[] = { CONV_DS_ADDR(ds_tags_nf), NULL };
83 
84 
85 	return ((CONV_TYPE_FMT_ALT(fmt_flags) == CONV_FMT_ALT_NF) ?
86 	    ds_nf : ds_cf);
87 }
88 
89 conv_iter_ret_t
conv_iter_cap_tags(Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)90 conv_iter_cap_tags(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
91     void *uvalue)
92 {
93 	return (conv_iter_ds(ELFOSABI_NONE, EM_NONE,
94 	    conv_cap_tag_strings(fmt_flags), func, uvalue));
95 }
96 
97 /*
98  * Given an array of elfcap_desc_t, and a count, call the specified
99  * iteration for each value in the array.
100  */
101 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)102 conv_iter_elfcap(const elfcap_desc_t *cdp, uint_t cnum,
103     Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func, void *uvalue)
104 {
105 	const char	*str;
106 
107 	fmt_flags = CONV_TYPE_FMT_ALT(fmt_flags);
108 
109 	for (; cnum-- > 0; cdp++) {
110 		/*
111 		 * Skip "reserved" bits. These are unassigned bits in the
112 		 * middle of the assigned range.
113 		 */
114 		if (cdp->c_val == 0)
115 			continue;
116 
117 		switch (fmt_flags) {
118 		default:
119 			str = cdp->c_full.s_str;
120 			break;
121 		case CONV_FMT_ALT_CFNP:
122 			str = cdp->c_uc.s_str;
123 			break;
124 		case CONV_FMT_ALT_NF:
125 			str = cdp->c_lc.s_str;
126 			break;
127 		}
128 
129 		if ((* func)(str, cdp->c_val, uvalue) == CONV_ITER_DONE)
130 			return (CONV_ITER_DONE);
131 	}
132 
133 	return (CONV_ITER_CONT);
134 }
135 
136 /*
137  * Iterate the strings for CA_SUNW_HW.
138  */
139 conv_iter_ret_t
conv_iter_cap_val_hw1(Half mach,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)140 conv_iter_cap_val_hw1(Half mach, Conv_fmt_flags_t fmt_flags,
141     conv_iter_cb_t func, void *uvalue)
142 {
143 	if ((mach == EM_386) || (mach == EM_486) ||
144 	    (mach == EM_AMD64) || (mach == CONV_MACH_ALL))
145 		if (conv_iter_elfcap(elfcap_getdesc_hw1_386(),
146 		    ELFCAP_NUM_HW1_386, fmt_flags, func, uvalue) ==
147 		    CONV_ITER_DONE)
148 			return (CONV_ITER_DONE);
149 
150 	if ((mach == EM_SPARC) || (mach == EM_SPARC32PLUS) ||
151 	    (mach == EM_SPARCV9) || (mach == CONV_MACH_ALL))
152 		if (conv_iter_elfcap(elfcap_getdesc_hw1_sparc(),
153 		    ELFCAP_NUM_HW1_SPARC, fmt_flags, func, uvalue) ==
154 		    CONV_ITER_DONE)
155 			return (CONV_ITER_DONE);
156 
157 	return (CONV_ITER_CONT);
158 }
159 
160 conv_iter_ret_t
161 /* ARGSUSED0 */
conv_iter_cap_val_hw2(Half mach,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)162 conv_iter_cap_val_hw2(Half mach, Conv_fmt_flags_t fmt_flags,
163     conv_iter_cb_t func, void *uvalue)
164 {
165 	if ((mach == EM_386) || (mach == EM_486) ||
166 	    (mach == EM_AMD64) || (mach == CONV_MACH_ALL))
167 		if (conv_iter_elfcap(elfcap_getdesc_hw2_386(),
168 		    ELFCAP_NUM_HW2_386, fmt_flags, func, uvalue) ==
169 		    CONV_ITER_DONE)
170 			return (CONV_ITER_DONE);
171 
172 	return (CONV_ITER_DONE);
173 }
174 
175 /*
176  * Iterate the strings for CA_SUNW_SF1
177  */
178 conv_iter_ret_t
conv_iter_cap_val_sf1(Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)179 conv_iter_cap_val_sf1(Conv_fmt_flags_t fmt_flags, conv_iter_cb_t func,
180     void *uvalue)
181 {
182 	return (conv_iter_elfcap(elfcap_getdesc_sf1(), ELFCAP_NUM_SF1,
183 	    fmt_flags, func, uvalue));
184 }
185 
186 conv_iter_ret_t
conv_iter_cap_val_hw3(Half mach,Conv_fmt_flags_t fmt_flags,conv_iter_cb_t func,void * uvalue)187 conv_iter_cap_val_hw3(Half mach, Conv_fmt_flags_t fmt_flags,
188     conv_iter_cb_t func, void *uvalue)
189 {
190 	if ((mach == EM_386) || (mach == EM_486) ||
191 	    (mach == EM_AMD64) || (mach == CONV_MACH_ALL))
192 		if (conv_iter_elfcap(elfcap_getdesc_hw3_386(),
193 		    ELFCAP_NUM_HW3_386, fmt_flags, func, uvalue) ==
194 		    CONV_ITER_DONE)
195 			return (CONV_ITER_DONE);
196 
197 	return (CONV_ITER_DONE);
198 }
199