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 ** 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 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 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 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 */ 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 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 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