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