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