1 1.3 mlelstv /* $NetBSD: util.c,v 1.3 2023/02/02 08:21:32 mlelstv Exp $ */ 2 1.1 nonaka 3 1.1 nonaka /*- 4 1.1 nonaka * Copyright (c) 2017 Netflix, Inc 5 1.1 nonaka * All rights reserved. 6 1.1 nonaka * 7 1.1 nonaka * Redistribution and use in source and binary forms, with or without 8 1.1 nonaka * modification, are permitted provided that the following conditions 9 1.1 nonaka * are met: 10 1.1 nonaka * 1. Redistributions of source code must retain the above copyright 11 1.1 nonaka * notice, this list of conditions and the following disclaimer. 12 1.1 nonaka * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 nonaka * notice, this list of conditions and the following disclaimer in the 14 1.1 nonaka * documentation and/or other materials provided with the distribution. 15 1.1 nonaka * 16 1.1 nonaka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 1.1 nonaka * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 1.1 nonaka * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 1.1 nonaka * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 1.1 nonaka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 1.1 nonaka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 1.1 nonaka * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 1.1 nonaka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 1.1 nonaka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 1.1 nonaka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 1.1 nonaka * SUCH DAMAGE. 27 1.1 nonaka */ 28 1.1 nonaka 29 1.1 nonaka #include <sys/cdefs.h> 30 1.1 nonaka #ifndef lint 31 1.3 mlelstv __RCSID("$NetBSD: util.c,v 1.3 2023/02/02 08:21:32 mlelstv Exp $"); 32 1.1 nonaka #if 0 33 1.1 nonaka __FBSDID("$FreeBSD: head/sbin/nvmecontrol/util.c 320423 2017-06-27 20:24:25Z imp $"); 34 1.1 nonaka #endif 35 1.1 nonaka #endif 36 1.1 nonaka 37 1.1 nonaka #include <sys/endian.h> 38 1.1 nonaka 39 1.1 nonaka #include <stdlib.h> 40 1.1 nonaka #include <string.h> 41 1.1 nonaka 42 1.1 nonaka #include "nvmectl.h" 43 1.1 nonaka #include "bn.h" 44 1.1 nonaka 45 1.1 nonaka void 46 1.1 nonaka nvme_strvis(u_char *dst, int dlen, const u_char *src, int slen) 47 1.1 nonaka { 48 1.1 nonaka #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377') 49 1.1 nonaka /* Trim leading and trailing blanks and NULs. */ 50 1.1 nonaka while (slen > 0 && STRVIS_ISWHITE(src[0])) 51 1.1 nonaka ++src, --slen; 52 1.1 nonaka while (slen > 0 && STRVIS_ISWHITE(src[slen - 1])) 53 1.1 nonaka --slen; 54 1.1 nonaka 55 1.1 nonaka while (slen > 0) { 56 1.1 nonaka if (*src < 0x20 || *src >= 0x80) { 57 1.1 nonaka /* non-printable characters */ 58 1.1 nonaka dlen -= 4; 59 1.1 nonaka if (dlen < 1) 60 1.1 nonaka break; 61 1.1 nonaka *dst++ = '\\'; 62 1.1 nonaka *dst++ = ((*src & 0300) >> 6) + '0'; 63 1.1 nonaka *dst++ = ((*src & 0070) >> 3) + '0'; 64 1.1 nonaka *dst++ = ((*src & 0007) >> 0) + '0'; 65 1.1 nonaka } else if (*src == '\\') { 66 1.1 nonaka /* quote characters */ 67 1.1 nonaka dlen -= 2; 68 1.1 nonaka if (dlen < 1) 69 1.1 nonaka break; 70 1.1 nonaka *dst++ = '\\'; 71 1.1 nonaka *dst++ = '\\'; 72 1.1 nonaka } else { 73 1.1 nonaka /* normal characters */ 74 1.1 nonaka if (--dlen < 1) 75 1.1 nonaka break; 76 1.1 nonaka *dst++ = *src; 77 1.1 nonaka } 78 1.1 nonaka ++src, --slen; 79 1.1 nonaka } 80 1.1 nonaka 81 1.1 nonaka *dst++ = 0; 82 1.1 nonaka } 83 1.1 nonaka 84 1.1 nonaka #define METRIX_PREFIX_BUFSIZ 17 85 1.1 nonaka #define NO_METRIX_PREFIX_BUFSIZ 42 86 1.1 nonaka 87 1.3 mlelstv static void 88 1.3 mlelstv unit_string(BIGNUM *bn, const char *unit, long scale, char *out, size_t len) 89 1.3 mlelstv { 90 1.3 mlelstv size_t ulen = strlen(unit); 91 1.3 mlelstv uint8_t tmp[4]; 92 1.3 mlelstv BN_CTX *ctx; 93 1.3 mlelstv BIGNUM *sn; 94 1.3 mlelstv 95 1.3 mlelstv if (6 + ulen + 3 >= len) 96 1.3 mlelstv return; 97 1.3 mlelstv 98 1.3 mlelstv if (scale > 1) { 99 1.3 mlelstv ctx = BN_CTX_new(); 100 1.3 mlelstv if (ctx == NULL) 101 1.3 mlelstv return; 102 1.3 mlelstv 103 1.3 mlelstv tmp[0] = (scale >> 24) & 0xff; 104 1.3 mlelstv tmp[1] = (scale >> 16) & 0xff; 105 1.3 mlelstv tmp[2] = (scale >> 8) & 0xff; 106 1.3 mlelstv tmp[3] = scale & 0xff; 107 1.3 mlelstv 108 1.3 mlelstv sn = BN_bin2bn(tmp, sizeof(tmp), NULL); 109 1.3 mlelstv if (sn != NULL) { 110 1.3 mlelstv BN_mul(bn, bn, sn, ctx); 111 1.3 mlelstv BN_free(sn); 112 1.3 mlelstv } 113 1.3 mlelstv 114 1.3 mlelstv BN_CTX_free(ctx); 115 1.3 mlelstv } 116 1.3 mlelstv 117 1.3 mlelstv strncpy(out, " (", len); 118 1.3 mlelstv humanize_bignum(out+2, 6 + ulen, bn, unit, HN_AUTOSCALE, HN_DECIMAL); 119 1.3 mlelstv strncat(out, ")", len); 120 1.3 mlelstv } 121 1.3 mlelstv 122 1.1 nonaka void 123 1.3 mlelstv print_bignum1(const char *title, uint64_t v[2], const char *suffix, 124 1.3 mlelstv const char *unit, long scale) 125 1.1 nonaka { 126 1.1 nonaka char buf[64]; 127 1.3 mlelstv char buf2[64]; 128 1.1 nonaka uint8_t tmp[16]; 129 1.2 nonaka uint64_t h, l; 130 1.2 nonaka 131 1.2 nonaka #if _BYTE_ORDER != _LITTLE_ENDIAN 132 1.2 nonaka /* Already Converted to host endian */ 133 1.2 nonaka h = v[0]; 134 1.2 nonaka l = v[1]; 135 1.2 nonaka memcpy(tmp, v, sizeof(tmp)); 136 1.2 nonaka #else 137 1.2 nonaka h = v[1]; 138 1.2 nonaka l = v[0]; 139 1.1 nonaka 140 1.1 nonaka tmp[ 0] = (h >> 56) & 0xff; 141 1.1 nonaka tmp[ 1] = (h >> 48) & 0xff; 142 1.1 nonaka tmp[ 2] = (h >> 40) & 0xff; 143 1.1 nonaka tmp[ 3] = (h >> 32) & 0xff; 144 1.1 nonaka tmp[ 4] = (h >> 24) & 0xff; 145 1.1 nonaka tmp[ 5] = (h >> 16) & 0xff; 146 1.1 nonaka tmp[ 6] = (h >> 8) & 0xff; 147 1.1 nonaka tmp[ 7] = h & 0xff; 148 1.1 nonaka tmp[ 8] = (l >> 56) & 0xff; 149 1.1 nonaka tmp[ 9] = (l >> 48) & 0xff; 150 1.1 nonaka tmp[10] = (l >> 40) & 0xff; 151 1.1 nonaka tmp[11] = (l >> 32) & 0xff; 152 1.1 nonaka tmp[12] = (l >> 24) & 0xff; 153 1.1 nonaka tmp[13] = (l >> 16) & 0xff; 154 1.1 nonaka tmp[14] = (l >> 8) & 0xff; 155 1.1 nonaka tmp[15] = l & 0xff; 156 1.2 nonaka #endif 157 1.1 nonaka 158 1.1 nonaka buf[0] = '\0'; 159 1.3 mlelstv buf2[0] = '\0'; 160 1.3 mlelstv 161 1.2 nonaka BIGNUM *bn = BN_bin2bn(tmp, sizeof(tmp), NULL); 162 1.1 nonaka if (bn != NULL) { 163 1.1 nonaka humanize_bignum(buf, METRIX_PREFIX_BUFSIZ + strlen(suffix), 164 1.3 mlelstv bn, suffix, HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE); 165 1.3 mlelstv if (unit) 166 1.3 mlelstv unit_string(bn, unit, scale, buf2, sizeof(buf2)); 167 1.1 nonaka BN_free(bn); 168 1.1 nonaka } 169 1.1 nonaka if (buf[0] == '\0') 170 1.2 nonaka snprintf(buf, sizeof(buf), "0x%016" PRIx64 "%016" PRIx64, h, l); 171 1.3 mlelstv printf("%-31s %s%s\n", title, buf, buf2); 172 1.3 mlelstv } 173 1.3 mlelstv 174 1.3 mlelstv void 175 1.3 mlelstv print_bignum(const char *title, uint64_t v[2], const char *suffix) 176 1.3 mlelstv { 177 1.3 mlelstv print_bignum1(title, v, suffix, NULL, 1); 178 1.1 nonaka } 179 1.1 nonaka 180 1.1 nonaka /* "Missing" from endian.h */ 181 1.1 nonaka uint64_t 182 1.1 nonaka le48dec(const void *pp) 183 1.1 nonaka { 184 1.1 nonaka uint8_t const *p = (uint8_t const *)pp; 185 1.1 nonaka 186 1.1 nonaka return (((uint64_t)le16dec(p + 4) << 32) | le32dec(p)); 187 1.1 nonaka } 188