14f680cc6SAli Bahrami /*
24f680cc6SAli Bahrami  * CDDL HEADER START
34f680cc6SAli Bahrami  *
44f680cc6SAli Bahrami  * The contents of this file are subject to the terms of the
54f680cc6SAli Bahrami  * Common Development and Distribution License (the "License").
64f680cc6SAli Bahrami  * You may not use this file except in compliance with the License.
74f680cc6SAli Bahrami  *
84f680cc6SAli Bahrami  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94f680cc6SAli Bahrami  * or http://www.opensolaris.org/os/licensing.
104f680cc6SAli Bahrami  * See the License for the specific language governing permissions
114f680cc6SAli Bahrami  * and limitations under the License.
124f680cc6SAli Bahrami  *
134f680cc6SAli Bahrami  * When distributing Covered Code, include this CDDL HEADER in each
144f680cc6SAli Bahrami  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154f680cc6SAli Bahrami  * If applicable, add the following below this CDDL HEADER, with the
164f680cc6SAli Bahrami  * fields enclosed by brackets "[]" replaced with your own identifying
174f680cc6SAli Bahrami  * information: Portions Copyright [yyyy] [name of copyright owner]
184f680cc6SAli Bahrami  *
194f680cc6SAli Bahrami  * CDDL HEADER END
204f680cc6SAli Bahrami  */
214f680cc6SAli Bahrami 
224f680cc6SAli Bahrami /*
2308278a5eSRod Evans  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
244f680cc6SAli Bahrami  * Use is subject to license terms.
25*56726c7eSRobert Mustacchi  *
26*56726c7eSRobert Mustacchi  * Copyright 2022 Oxide Computer Company
274f680cc6SAli Bahrami  */
284f680cc6SAli Bahrami 
294f680cc6SAli Bahrami /*
304f680cc6SAli Bahrami  * String conversion routine for hardware capabilities types.
314f680cc6SAli Bahrami  */
324f680cc6SAli Bahrami #include	<strings.h>
334f680cc6SAli Bahrami #include	<stdio.h>
344f680cc6SAli Bahrami #include	<_machelf.h>
354f680cc6SAli Bahrami #include	<elfcap.h>
364f680cc6SAli Bahrami #include	"cap_msg.h"
374f680cc6SAli Bahrami #include	"_conv.h"
384f680cc6SAli Bahrami 
394f680cc6SAli Bahrami static int
conv_cap(Xword val,char * str,size_t len,Half mach,Conv_fmt_flags_t fmt_flags,elfcap_to_str_func_t * fptr)4008278a5eSRod Evans conv_cap(Xword val, char *str, size_t len, Half mach,
414f680cc6SAli Bahrami     Conv_fmt_flags_t fmt_flags, elfcap_to_str_func_t *fptr)
424f680cc6SAli Bahrami {
434f680cc6SAli Bahrami 	size_t	_len;
444f680cc6SAli Bahrami 	int do_bkt = (fmt_flags & CONV_FMT_NOBKT) == 0;
454f680cc6SAli Bahrami 
464f680cc6SAli Bahrami 	/*
474f680cc6SAli Bahrami 	 * Note that for the purposes of this routine, I consider
484f680cc6SAli Bahrami 	 * CONV_FMT_NOBKT to mean no brackets, or anything that
494f680cc6SAli Bahrami 	 * is placed outside of them. We also drop the hex version
504f680cc6SAli Bahrami 	 * of the flags that are put in front of the opening bracket.
514f680cc6SAli Bahrami 	 */
524f680cc6SAli Bahrami 	if (do_bkt) {
534f680cc6SAli Bahrami 		_len = sprintf(str, MSG_ORIG(MSG_GBL_OSQBRKT), EC_XWORD(val));
544f680cc6SAli Bahrami 
554f680cc6SAli Bahrami 		len -= _len;
564f680cc6SAli Bahrami 		str += _len;
574f680cc6SAli Bahrami 	}
584f680cc6SAli Bahrami 
594f680cc6SAli Bahrami 	if ((*fptr)(ELFCAP_STYLE_UC, val, str, len, ELFCAP_FMT_SNGSPACE,
604f680cc6SAli Bahrami 	    mach) != 0)
614f680cc6SAli Bahrami 		return (0);
624f680cc6SAli Bahrami 
634f680cc6SAli Bahrami 	if (do_bkt) {
644f680cc6SAli Bahrami 		_len = strlen(str);
654f680cc6SAli Bahrami 		if ((len - _len) >= MSG_GBL_CSQBRKT_SIZE) {
664f680cc6SAli Bahrami 			str += _len;
674f680cc6SAli Bahrami 			(void) strcpy(str, MSG_ORIG(MSG_GBL_CSQBRKT));
684f680cc6SAli Bahrami 		}
694f680cc6SAli Bahrami 	}
704f680cc6SAli Bahrami 	return (1);
714f680cc6SAli Bahrami }
724f680cc6SAli Bahrami 
734f680cc6SAli Bahrami const char *
conv_cap_val_hw1(Xword val,Half mach,Conv_fmt_flags_t fmt_flags,Conv_cap_val_hw1_buf_t * cap_val_hw1_buf)744f680cc6SAli Bahrami conv_cap_val_hw1(Xword val, Half mach, Conv_fmt_flags_t fmt_flags,
754f680cc6SAli Bahrami     Conv_cap_val_hw1_buf_t *cap_val_hw1_buf)
764f680cc6SAli Bahrami {
774f680cc6SAli Bahrami 	if (val == 0)
784f680cc6SAli Bahrami 		return (MSG_ORIG(MSG_GBL_ZERO));
794f680cc6SAli Bahrami 
8008278a5eSRod Evans 	if (conv_cap(val, cap_val_hw1_buf->buf, sizeof (cap_val_hw1_buf->buf),
814f680cc6SAli Bahrami 	    mach, fmt_flags, elfcap_hw1_to_str) == 0)
824f680cc6SAli Bahrami 		return (conv_invalid_val(&cap_val_hw1_buf->inv_buf, val, 0));
834f680cc6SAli Bahrami 	return ((const char *)cap_val_hw1_buf->buf);
844f680cc6SAli Bahrami }
854f680cc6SAli Bahrami 
8608278a5eSRod Evans const char *
conv_cap_val_hw2(Xword val,Half mach,Conv_fmt_flags_t fmt_flags,Conv_cap_val_hw2_buf_t * cap_val_hw2_buf)8708278a5eSRod Evans conv_cap_val_hw2(Xword val, Half mach, Conv_fmt_flags_t fmt_flags,
8808278a5eSRod Evans     Conv_cap_val_hw2_buf_t *cap_val_hw2_buf)
8908278a5eSRod Evans {
9008278a5eSRod Evans 	if (val == 0)
9108278a5eSRod Evans 		return (MSG_ORIG(MSG_GBL_ZERO));
9208278a5eSRod Evans 
9308278a5eSRod Evans 	if (conv_cap(val, cap_val_hw2_buf->buf, sizeof (cap_val_hw2_buf->buf),
9408278a5eSRod Evans 	    mach, fmt_flags, elfcap_hw2_to_str) == 0)
9508278a5eSRod Evans 		return (conv_invalid_val(&cap_val_hw2_buf->inv_buf, val, 0));
9608278a5eSRod Evans 	return ((const char *)cap_val_hw2_buf->buf);
9708278a5eSRod Evans }
9808278a5eSRod Evans 
994f680cc6SAli Bahrami const char *
conv_cap_val_sf1(Xword val,Half mach,Conv_fmt_flags_t fmt_flags,Conv_cap_val_sf1_buf_t * cap_val_sf1_buf)1004f680cc6SAli Bahrami conv_cap_val_sf1(Xword val, Half mach, Conv_fmt_flags_t fmt_flags,
1014f680cc6SAli Bahrami     Conv_cap_val_sf1_buf_t *cap_val_sf1_buf)
1024f680cc6SAli Bahrami {
1034f680cc6SAli Bahrami 	if (val == 0)
1044f680cc6SAli Bahrami 		return (MSG_ORIG(MSG_GBL_ZERO));
1054f680cc6SAli Bahrami 
10608278a5eSRod Evans 	if (conv_cap(val, cap_val_sf1_buf->buf, sizeof (cap_val_sf1_buf->buf),
1074f680cc6SAli Bahrami 	    mach, fmt_flags, elfcap_sf1_to_str) == 0)
1084f680cc6SAli Bahrami 		return (conv_invalid_val(&cap_val_sf1_buf->inv_buf, val, 0));
1094f680cc6SAli Bahrami 	return ((const char *)cap_val_sf1_buf->buf);
1104f680cc6SAli Bahrami }
1114f680cc6SAli Bahrami 
112*56726c7eSRobert Mustacchi const char *
conv_cap_val_hw3(Xword val,Half mach,Conv_fmt_flags_t fmt_flags,Conv_cap_val_hw3_buf_t * cap_val_hw3_buf)113*56726c7eSRobert Mustacchi conv_cap_val_hw3(Xword val, Half mach, Conv_fmt_flags_t fmt_flags,
114*56726c7eSRobert Mustacchi     Conv_cap_val_hw3_buf_t *cap_val_hw3_buf)
115*56726c7eSRobert Mustacchi {
116*56726c7eSRobert Mustacchi 	if (val == 0)
117*56726c7eSRobert Mustacchi 		return (MSG_ORIG(MSG_GBL_ZERO));
118*56726c7eSRobert Mustacchi 
119*56726c7eSRobert Mustacchi 	if (conv_cap(val, cap_val_hw3_buf->buf, sizeof (cap_val_hw3_buf->buf),
120*56726c7eSRobert Mustacchi 	    mach, fmt_flags, elfcap_hw3_to_str) == 0)
121*56726c7eSRobert Mustacchi 		return (conv_invalid_val(&cap_val_hw3_buf->inv_buf, val, 0));
122*56726c7eSRobert Mustacchi 	return ((const char *)cap_val_hw3_buf->buf);
123*56726c7eSRobert Mustacchi }
124*56726c7eSRobert Mustacchi 
1254f680cc6SAli Bahrami const char *
conv_cap_tag(Xword tag,Conv_fmt_flags_t fmt_flags,Conv_inv_buf_t * inv_buf)1264f680cc6SAli Bahrami conv_cap_tag(Xword tag, Conv_fmt_flags_t fmt_flags, Conv_inv_buf_t *inv_buf)
1274f680cc6SAli Bahrami {
1284f680cc6SAli Bahrami #ifdef _ELF64
1294f680cc6SAli Bahrami 	/*
1304f680cc6SAli Bahrami 	 * Valid tags all fit in 32-bits, so a value larger than that
1314f680cc6SAli Bahrami 	 * is garbage. conv_map_ds() sees 32-bit values, so test for garbage
1324f680cc6SAli Bahrami 	 * here before passing it on.
1334f680cc6SAli Bahrami 	 *
1344f680cc6SAli Bahrami 	 * Since there are no valid tags with a value > 32-bits, there
1354f680cc6SAli Bahrami 	 * is no reason to expend effort decoding the low order bits.
1364f680cc6SAli Bahrami 	 */
1374f680cc6SAli Bahrami 	if (tag & 0xffffffff00000000)
1384f680cc6SAli Bahrami 		return (conv_invalid_val(inv_buf, tag, fmt_flags));
1394f680cc6SAli Bahrami #endif
1404f680cc6SAli Bahrami 
1414f680cc6SAli Bahrami 	return (conv_map_ds(ELFOSABI_NONE, EM_NONE, tag,
1424f680cc6SAli Bahrami 	    conv_cap_tag_strings(fmt_flags), fmt_flags, inv_buf));
1434f680cc6SAli Bahrami }
1444f680cc6SAli Bahrami 
1454f680cc6SAli Bahrami const char *
conv_cap_val(Xword tag,Xword val,Half mach,Conv_fmt_flags_t fmt_flags,Conv_cap_val_buf_t * cap_val_buf)14608278a5eSRod Evans conv_cap_val(Xword tag, Xword val, Half mach, Conv_fmt_flags_t fmt_flags,
14708278a5eSRod Evans     Conv_cap_val_buf_t *cap_val_buf)
1484f680cc6SAli Bahrami {
14908278a5eSRod Evans 	switch (tag) {
15008278a5eSRod Evans 	case CA_SUNW_HW_1:
15108278a5eSRod Evans 		return (conv_cap_val_hw1(val, mach, fmt_flags,
1524f680cc6SAli Bahrami 		    &cap_val_buf->cap_val_hw1_buf));
15308278a5eSRod Evans 
15408278a5eSRod Evans 	case CA_SUNW_SF_1:
15508278a5eSRod Evans 		return (conv_cap_val_sf1(val, mach, fmt_flags,
1564f680cc6SAli Bahrami 		    &cap_val_buf->cap_val_sf1_buf));
15708278a5eSRod Evans 
15808278a5eSRod Evans 	case CA_SUNW_HW_2:
15908278a5eSRod Evans 		return (conv_cap_val_hw2(val, mach, fmt_flags,
16008278a5eSRod Evans 		    &cap_val_buf->cap_val_hw2_buf));
16108278a5eSRod Evans 
162*56726c7eSRobert Mustacchi 	case CA_SUNW_HW_3:
163*56726c7eSRobert Mustacchi 		return (conv_cap_val_hw3(val, mach, fmt_flags,
164*56726c7eSRobert Mustacchi 		    &cap_val_buf->cap_val_hw3_buf));
165*56726c7eSRobert Mustacchi 
16608278a5eSRod Evans 	default:
1674f680cc6SAli Bahrami 		return (conv_invalid_val(&cap_val_buf->inv_buf, val, 0));
16808278a5eSRod Evans 	}
1694f680cc6SAli Bahrami }
170