1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2022 Oxide Computer Company 14 */ 15 16 /* 17 * This tool is used to try and figure out what the value of various static 18 * buffers should be and if the current compile time defaults are correct. In 19 * particular, this covers the various elfcap values and is used to drive how we 20 * calculate the overall size definition. 21 * 22 * To calculate this, we assume the following: 23 * 24 * o We are using the ELFCAP_FMT_PIPSPACE as that is the longest. We don't 25 * have access to the actual strings right now. 26 * o We are using the ELFCAP_STYLE_FULL variant of the name as that's the 27 * longest. 28 * o We are going to have leftover bits that we don't know (unless we have 29 * 32-bits defined). This uses the 0x%x format and therefore is 10 30 * characters. 31 * o We check all architectures set of values and take the largest. 32 * 33 * While elfcap related information is in multiple places in the build, sgs and 34 * libconv are the places that seem most intertwined. In particular, we believe 35 * it's important that this program execute as part of make check and also get 36 * rebuilt normally as part of a build. This also allows one to iterate in 37 * cmd/sgs which is the most common place that you're working in when adding new 38 * hardware capabilities. By making it a part of the cmd/sgs suite, that also 39 * ensures that normal build logic always rebuilds this program with changes to 40 * elfcap.[ch]. 41 */ 42 43 #include <stdio.h> 44 #include <elfcap.h> 45 #include <sys/sysmacros.h> 46 #include <stdlib.h> 47 48 /* 49 * The length of 0x%x. 50 */ 51 #define ECS_UNKNOWN 10 52 53 typedef const elfcap_desc_t *(*elfcap_getdesc_f)(void); 54 55 typedef struct elfcap_getdesc { 56 uint32_t eg_nents; 57 elfcap_getdesc_f eg_func; 58 } elfcap_getdesc_t; 59 60 typedef struct elfcap_case { 61 const char *ec_tag; 62 size_t ec_header; 63 elfcap_getdesc_t ec_descs[2]; 64 } elfcap_case_t; 65 66 const elfcap_case_t elfcaps[] = { 67 { "ELFCAP_SF1_BUFSIZE", ELFCAP_SF1_BUFSIZE, { 68 { ELFCAP_NUM_SF1, elfcap_getdesc_sf1 }, 69 { 0, NULL } 70 } }, 71 { "ELFCAP_HW1_BUFSIZE", ELFCAP_HW1_BUFSIZE, { 72 { ELFCAP_NUM_HW1_386, elfcap_getdesc_hw1_386 }, 73 { ELFCAP_NUM_HW1_SPARC, elfcap_getdesc_hw1_sparc } 74 } }, 75 { "ELFCAP_HW1_BUFSIZE", ELFCAP_HW2_BUFSIZE, { 76 { ELFCAP_NUM_HW2_386, elfcap_getdesc_hw2_386 }, 77 { 0, NULL } 78 } }, 79 { "ELFCAP_HW1_BUFSIZE", ELFCAP_HW3_BUFSIZE, { 80 { ELFCAP_NUM_HW3_386, elfcap_getdesc_hw3_386 }, 81 { 0, NULL } 82 } }, 83 }; 84 85 static size_t 86 elfcap_calc_len(const elfcap_desc_t *desc, uint32_t nents, size_t space) 87 { 88 size_t len = 0; 89 90 for (uint32_t i = 0; i < nents; i++) { 91 len += desc[i].c_full.s_len; 92 if (i > 0) { 93 len += space; 94 } 95 } 96 97 if (nents < 32) { 98 len += space + ECS_UNKNOWN; 99 } 100 101 /* 102 * Finally, add one for a terminator and we add an 8 character buffer in 103 * case we screwed up. 104 */ 105 len += 9; 106 107 return (len); 108 } 109 110 static size_t 111 elfcap_max_len(const elfcap_case_t *ec, size_t slen) 112 { 113 size_t max = 0; 114 115 for (size_t i = 0; i < ARRAY_SIZE(ec->ec_descs); i++) { 116 const elfcap_desc_t *desc; 117 size_t len; 118 119 if (ec->ec_descs[i].eg_func == NULL) 120 continue; 121 122 desc = ec->ec_descs[i].eg_func(); 123 len = elfcap_calc_len(desc, ec->ec_descs[i].eg_nents, slen); 124 if (len > max) 125 max = len; 126 } 127 128 return (max); 129 } 130 131 int 132 main(void) 133 { 134 size_t slen; 135 const elfcap_str_t *strs; 136 int ret = EXIT_SUCCESS; 137 138 strs = elfcap_getdesc_formats(); 139 slen = strs[ELFCAP_FMT_PIPSPACE].s_len; 140 141 for (size_t i = 0; i < ARRAY_SIZE(elfcaps); i++) { 142 size_t out = elfcap_max_len(&elfcaps[i], slen); 143 144 if (out != elfcaps[i].ec_header) { 145 (void) fprintf(stderr, "elfcap size for %s is not " 146 "expected value!\n\tCurrent value is %zu, should " 147 "be %zu\n", elfcaps[i].ec_tag, elfcaps[i].ec_header, 148 out); 149 ret = EXIT_FAILURE; 150 } 151 } 152 153 if (ret != EXIT_SUCCESS) { 154 (void) fprintf(stderr, "please update $SRC/common/elfcap/" 155 "elfcap.h and $SRC/cmd/sgs/include/conv.h with the new " 156 "values reported above\n"); 157 } 158 159 return (ret); 160 } 161