1 1.2 riastrad /* $NetBSD: mkregtable.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $ */ 2 1.2 riastrad 3 1.3 riastrad // SPDX-License-Identifier: MIT 4 1.1 riastrad /* utility to create the register check tables 5 1.1 riastrad * this includes inlined list.h safe for userspace. 6 1.1 riastrad * 7 1.1 riastrad * Copyright 2009 Jerome Glisse 8 1.1 riastrad * Copyright 2009 Red Hat Inc. 9 1.1 riastrad * 10 1.1 riastrad * Authors: 11 1.1 riastrad * Jerome Glisse 12 1.1 riastrad * Dave Airlie 13 1.1 riastrad */ 14 1.1 riastrad 15 1.2 riastrad #include <sys/cdefs.h> 16 1.2 riastrad __KERNEL_RCSID(0, "$NetBSD: mkregtable.c,v 1.3 2021/12/18 23:45:42 riastradh Exp $"); 17 1.2 riastrad 18 1.1 riastrad #include <sys/types.h> 19 1.1 riastrad #include <stdlib.h> 20 1.1 riastrad #include <string.h> 21 1.1 riastrad #include <stdio.h> 22 1.1 riastrad #include <regex.h> 23 1.1 riastrad #include <libgen.h> 24 1.1 riastrad 25 1.1 riastrad #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 26 1.1 riastrad /** 27 1.1 riastrad * container_of - cast a member of a structure out to the containing structure 28 1.1 riastrad * @ptr: the pointer to the member. 29 1.1 riastrad * @type: the type of the container struct this is embedded in. 30 1.1 riastrad * @member: the name of the member within the struct. 31 1.1 riastrad * 32 1.1 riastrad */ 33 1.1 riastrad #define container_of(ptr, type, member) ({ \ 34 1.1 riastrad const typeof(((type *)0)->member)*__mptr = (ptr); \ 35 1.1 riastrad (type *)((char *)__mptr - offsetof(type, member)); }) 36 1.1 riastrad 37 1.1 riastrad /* 38 1.1 riastrad * Simple doubly linked list implementation. 39 1.1 riastrad * 40 1.1 riastrad * Some of the internal functions ("__xxx") are useful when 41 1.1 riastrad * manipulating whole lists rather than single entries, as 42 1.1 riastrad * sometimes we already know the next/prev entries and we can 43 1.1 riastrad * generate better code by using them directly rather than 44 1.1 riastrad * using the generic single-entry routines. 45 1.1 riastrad */ 46 1.1 riastrad 47 1.1 riastrad struct list_head { 48 1.1 riastrad struct list_head *next, *prev; 49 1.1 riastrad }; 50 1.1 riastrad 51 1.1 riastrad 52 1.1 riastrad static inline void INIT_LIST_HEAD(struct list_head *list) 53 1.1 riastrad { 54 1.1 riastrad list->next = list; 55 1.1 riastrad list->prev = list; 56 1.1 riastrad } 57 1.1 riastrad 58 1.1 riastrad /* 59 1.1 riastrad * Insert a new entry between two known consecutive entries. 60 1.1 riastrad * 61 1.1 riastrad * This is only for internal list manipulation where we know 62 1.1 riastrad * the prev/next entries already! 63 1.1 riastrad */ 64 1.1 riastrad #ifndef CONFIG_DEBUG_LIST 65 1.1 riastrad static inline void __list_add(struct list_head *new, 66 1.1 riastrad struct list_head *prev, struct list_head *next) 67 1.1 riastrad { 68 1.1 riastrad next->prev = new; 69 1.1 riastrad new->next = next; 70 1.1 riastrad new->prev = prev; 71 1.1 riastrad prev->next = new; 72 1.1 riastrad } 73 1.1 riastrad #else 74 1.1 riastrad extern void __list_add(struct list_head *new, 75 1.1 riastrad struct list_head *prev, struct list_head *next); 76 1.1 riastrad #endif 77 1.1 riastrad 78 1.1 riastrad /** 79 1.1 riastrad * list_add_tail - add a new entry 80 1.1 riastrad * @new: new entry to be added 81 1.1 riastrad * @head: list head to add it before 82 1.1 riastrad * 83 1.1 riastrad * Insert a new entry before the specified head. 84 1.1 riastrad * This is useful for implementing queues. 85 1.1 riastrad */ 86 1.1 riastrad static inline void list_add_tail(struct list_head *new, struct list_head *head) 87 1.1 riastrad { 88 1.1 riastrad __list_add(new, head->prev, head); 89 1.1 riastrad } 90 1.1 riastrad 91 1.1 riastrad /** 92 1.1 riastrad * list_entry - get the struct for this entry 93 1.1 riastrad * @ptr: the &struct list_head pointer. 94 1.1 riastrad * @type: the type of the struct this is embedded in. 95 1.2 riastrad * @member: the name of the list_head within the struct. 96 1.1 riastrad */ 97 1.1 riastrad #define list_entry(ptr, type, member) \ 98 1.1 riastrad container_of(ptr, type, member) 99 1.1 riastrad 100 1.1 riastrad /** 101 1.1 riastrad * list_for_each_entry - iterate over list of given type 102 1.1 riastrad * @pos: the type * to use as a loop cursor. 103 1.1 riastrad * @head: the head for your list. 104 1.2 riastrad * @member: the name of the list_head within the struct. 105 1.1 riastrad */ 106 1.1 riastrad #define list_for_each_entry(pos, head, member) \ 107 1.1 riastrad for (pos = list_entry((head)->next, typeof(*pos), member); \ 108 1.1 riastrad &pos->member != (head); \ 109 1.1 riastrad pos = list_entry(pos->member.next, typeof(*pos), member)) 110 1.1 riastrad 111 1.1 riastrad struct offset { 112 1.1 riastrad struct list_head list; 113 1.1 riastrad unsigned offset; 114 1.1 riastrad }; 115 1.1 riastrad 116 1.1 riastrad struct table { 117 1.1 riastrad struct list_head offsets; 118 1.1 riastrad unsigned offset_max; 119 1.1 riastrad unsigned nentry; 120 1.1 riastrad unsigned *table; 121 1.1 riastrad char *gpu_prefix; 122 1.1 riastrad }; 123 1.1 riastrad 124 1.1 riastrad static struct offset *offset_new(unsigned o) 125 1.1 riastrad { 126 1.1 riastrad struct offset *offset; 127 1.1 riastrad 128 1.1 riastrad offset = (struct offset *)malloc(sizeof(struct offset)); 129 1.1 riastrad if (offset) { 130 1.1 riastrad INIT_LIST_HEAD(&offset->list); 131 1.1 riastrad offset->offset = o; 132 1.1 riastrad } 133 1.1 riastrad return offset; 134 1.1 riastrad } 135 1.1 riastrad 136 1.1 riastrad static void table_offset_add(struct table *t, struct offset *offset) 137 1.1 riastrad { 138 1.1 riastrad list_add_tail(&offset->list, &t->offsets); 139 1.1 riastrad } 140 1.1 riastrad 141 1.1 riastrad static void table_init(struct table *t) 142 1.1 riastrad { 143 1.1 riastrad INIT_LIST_HEAD(&t->offsets); 144 1.1 riastrad t->offset_max = 0; 145 1.1 riastrad t->nentry = 0; 146 1.1 riastrad t->table = NULL; 147 1.1 riastrad } 148 1.1 riastrad 149 1.1 riastrad static void table_print(struct table *t) 150 1.1 riastrad { 151 1.1 riastrad unsigned nlloop, i, j, n, c, id; 152 1.1 riastrad 153 1.1 riastrad nlloop = (t->nentry + 3) / 4; 154 1.1 riastrad c = t->nentry; 155 1.1 riastrad printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix, 156 1.1 riastrad t->nentry); 157 1.1 riastrad for (i = 0, id = 0; i < nlloop; i++) { 158 1.1 riastrad n = 4; 159 1.1 riastrad if (n > c) 160 1.1 riastrad n = c; 161 1.1 riastrad c -= n; 162 1.1 riastrad for (j = 0; j < n; j++) { 163 1.1 riastrad if (j == 0) 164 1.1 riastrad printf("\t"); 165 1.1 riastrad else 166 1.1 riastrad printf(" "); 167 1.1 riastrad printf("0x%08X,", t->table[id++]); 168 1.1 riastrad } 169 1.1 riastrad printf("\n"); 170 1.1 riastrad } 171 1.1 riastrad printf("};\n"); 172 1.1 riastrad } 173 1.1 riastrad 174 1.1 riastrad static int table_build(struct table *t) 175 1.1 riastrad { 176 1.1 riastrad struct offset *offset; 177 1.1 riastrad unsigned i, m; 178 1.1 riastrad 179 1.1 riastrad t->nentry = ((t->offset_max >> 2) + 31) / 32; 180 1.1 riastrad t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry); 181 1.1 riastrad if (t->table == NULL) 182 1.1 riastrad return -1; 183 1.1 riastrad memset(t->table, 0xff, sizeof(unsigned) * t->nentry); 184 1.1 riastrad list_for_each_entry(offset, &t->offsets, list) { 185 1.1 riastrad i = (offset->offset >> 2) / 32; 186 1.1 riastrad m = (offset->offset >> 2) & 31; 187 1.1 riastrad m = 1 << m; 188 1.1 riastrad t->table[i] ^= m; 189 1.1 riastrad } 190 1.1 riastrad return 0; 191 1.1 riastrad } 192 1.1 riastrad 193 1.1 riastrad static char gpu_name[10]; 194 1.1 riastrad static int parser_auth(struct table *t, const char *filename) 195 1.1 riastrad { 196 1.1 riastrad FILE *file; 197 1.1 riastrad regex_t mask_rex; 198 1.1 riastrad regmatch_t match[4]; 199 1.1 riastrad char buf[1024]; 200 1.1 riastrad size_t end; 201 1.1 riastrad int len; 202 1.1 riastrad int done = 0; 203 1.1 riastrad int r; 204 1.1 riastrad unsigned o; 205 1.1 riastrad struct offset *offset; 206 1.1 riastrad char last_reg_s[10]; 207 1.1 riastrad int last_reg; 208 1.1 riastrad 209 1.1 riastrad if (regcomp 210 1.1 riastrad (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { 211 1.1 riastrad fprintf(stderr, "Failed to compile regular expression\n"); 212 1.1 riastrad return -1; 213 1.1 riastrad } 214 1.1 riastrad file = fopen(filename, "r"); 215 1.1 riastrad if (file == NULL) { 216 1.1 riastrad fprintf(stderr, "Failed to open: %s\n", filename); 217 1.1 riastrad return -1; 218 1.1 riastrad } 219 1.1 riastrad fseek(file, 0, SEEK_END); 220 1.1 riastrad end = ftell(file); 221 1.1 riastrad fseek(file, 0, SEEK_SET); 222 1.1 riastrad 223 1.1 riastrad /* get header */ 224 1.1 riastrad if (fgets(buf, 1024, file) == NULL) { 225 1.1 riastrad fclose(file); 226 1.1 riastrad return -1; 227 1.1 riastrad } 228 1.1 riastrad 229 1.1 riastrad /* first line will contain the last register 230 1.1 riastrad * and gpu name */ 231 1.1 riastrad sscanf(buf, "%9s %9s", gpu_name, last_reg_s); 232 1.1 riastrad t->gpu_prefix = gpu_name; 233 1.1 riastrad last_reg = strtol(last_reg_s, NULL, 16); 234 1.1 riastrad 235 1.1 riastrad do { 236 1.1 riastrad if (fgets(buf, 1024, file) == NULL) { 237 1.1 riastrad fclose(file); 238 1.1 riastrad return -1; 239 1.1 riastrad } 240 1.1 riastrad len = strlen(buf); 241 1.1 riastrad if (ftell(file) == end) 242 1.1 riastrad done = 1; 243 1.1 riastrad if (len) { 244 1.1 riastrad r = regexec(&mask_rex, buf, 4, match, 0); 245 1.1 riastrad if (r == REG_NOMATCH) { 246 1.1 riastrad } else if (r) { 247 1.1 riastrad fprintf(stderr, 248 1.1 riastrad "Error matching regular expression %d in %s\n", 249 1.1 riastrad r, filename); 250 1.1 riastrad fclose(file); 251 1.1 riastrad return -1; 252 1.1 riastrad } else { 253 1.1 riastrad buf[match[0].rm_eo] = 0; 254 1.1 riastrad buf[match[1].rm_eo] = 0; 255 1.1 riastrad buf[match[2].rm_eo] = 0; 256 1.1 riastrad o = strtol(&buf[match[1].rm_so], NULL, 16); 257 1.1 riastrad offset = offset_new(o); 258 1.1 riastrad table_offset_add(t, offset); 259 1.1 riastrad if (o > t->offset_max) 260 1.1 riastrad t->offset_max = o; 261 1.1 riastrad } 262 1.1 riastrad } 263 1.1 riastrad } while (!done); 264 1.1 riastrad fclose(file); 265 1.1 riastrad if (t->offset_max < last_reg) 266 1.1 riastrad t->offset_max = last_reg; 267 1.1 riastrad return table_build(t); 268 1.1 riastrad } 269 1.1 riastrad 270 1.1 riastrad int main(int argc, char *argv[]) 271 1.1 riastrad { 272 1.1 riastrad struct table t; 273 1.1 riastrad 274 1.1 riastrad if (argc != 2) { 275 1.1 riastrad fprintf(stderr, "Usage: %s <authfile>\n", argv[0]); 276 1.1 riastrad exit(1); 277 1.1 riastrad } 278 1.1 riastrad table_init(&t); 279 1.1 riastrad if (parser_auth(&t, argv[1])) { 280 1.1 riastrad fprintf(stderr, "Failed to parse file %s\n", argv[1]); 281 1.1 riastrad return -1; 282 1.1 riastrad } 283 1.1 riastrad table_print(&t); 284 1.1 riastrad return 0; 285 1.1 riastrad } 286