xref: /linux/drivers/gpu/drm/xe/xe_gen_wa_oob.c (revision b8e85e6f3a09fc56b0ff574887798962ef8a8f80)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright © 2023 Intel Corporation
4  */
5 
6 #define _GNU_SOURCE
7 #include <ctype.h>
8 #include <errno.h>
9 #include <stdbool.h>
10 #include <stdio.h>
11 #include <string.h>
12 
13 #define HEADER \
14 	"// SPDX-License-Identifier: MIT\n" \
15 	"\n" \
16 	"/*\n" \
17 	" * DO NOT MODIFY.\n" \
18 	" *\n" \
19 	" * This file was generated from rules: %s\n" \
20 	" */\n" \
21 	"#ifndef _GENERATED_XE_WA_OOB_\n" \
22 	"#define _GENERATED_XE_WA_OOB_\n" \
23 	"\n" \
24 	"enum {\n"
25 
26 #define FOOTER \
27 	"};\n" \
28 	"\n" \
29 	"#endif\n"
30 
31 static void print_usage(FILE *f)
32 {
33 	fprintf(f, "usage: %s <input-rule-file> <generated-c-source-file> <generated-c-header-file>\n",
34 		program_invocation_short_name);
35 }
36 
37 static void print_parse_error(const char *err_msg, const char *line,
38 			      unsigned int lineno)
39 {
40 	fprintf(stderr, "ERROR: %s\nERROR: %u: %.60s\n",
41 		err_msg, lineno, line);
42 }
43 
44 static char *strip(char *line, size_t linelen)
45 {
46 	while (isspace(*(line + linelen)))
47 		linelen--;
48 
49 	line[linelen - 1] = '\0';
50 
51 	return  line + strspn(line, " \f\n\r\t\v");
52 }
53 
54 #define MAX_LINE_LEN 4096
55 static int parse(FILE *input, FILE *csource, FILE *cheader)
56 {
57 	char line[MAX_LINE_LEN + 1];
58 	char *name, *prev_name = NULL, *rules;
59 	unsigned int lineno = 0, idx = 0;
60 
61 	while (fgets(line, sizeof(line), input)) {
62 		size_t linelen;
63 		bool is_continuation;
64 
65 		if (line[0] == '\0' || line[0] == '#' || line[0] == '\n') {
66 			lineno++;
67 			continue;
68 		}
69 
70 		linelen = strlen(line);
71 		if (linelen == MAX_LINE_LEN) {
72 			print_parse_error("line too long", line, lineno);
73 			return -EINVAL;
74 		}
75 
76 		is_continuation = isspace(line[0]);
77 		name = strip(line, linelen);
78 
79 		if (!is_continuation) {
80 			name = strtok(name, " \t");
81 			rules = strtok(NULL, "");
82 		} else {
83 			if (!prev_name) {
84 				print_parse_error("invalid rule continuation",
85 						  line, lineno);
86 				return -EINVAL;
87 			}
88 
89 			rules = name;
90 			name = NULL;
91 		}
92 
93 		if (rules[0] == '\0') {
94 			print_parse_error("invalid empty rule\n", line, lineno);
95 			return -EINVAL;
96 		}
97 
98 		if (name) {
99 			fprintf(cheader, "\tXE_WA_OOB_%s = %u,\n", name, idx);
100 			fprintf(csource, "{ XE_RTP_NAME(\"%s\"), XE_RTP_RULES(%s) },\n",
101 				name, rules);
102 		} else {
103 			fprintf(csource, "{ XE_RTP_NAME(NULL), XE_RTP_RULES(%s) },\n",
104 				rules);
105 		}
106 
107 		idx++;
108 		lineno++;
109 		if (!is_continuation)
110 			prev_name = name;
111 	}
112 
113 	fprintf(cheader, "\t_XE_WA_OOB_COUNT = %u\n", idx);
114 
115 	return 0;
116 }
117 
118 int main(int argc, const char *argv[])
119 {
120 	enum {
121 		ARGS_INPUT,
122 		ARGS_CSOURCE,
123 		ARGS_CHEADER,
124 		_ARGS_COUNT
125 	};
126 	struct {
127 		const char *fn;
128 		const char *mode;
129 		FILE *f;
130 	} args[] = {
131 		[ARGS_INPUT] = { .fn = argv[1], .mode = "r" },
132 		[ARGS_CSOURCE] = { .fn = argv[2], .mode = "w" },
133 		[ARGS_CHEADER] = { .fn = argv[3], .mode = "w" },
134 	};
135 	int ret = 1;
136 
137 	if (argc < 3) {
138 		fprintf(stderr, "ERROR: wrong arguments\n");
139 		print_usage(stderr);
140 		return 1;
141 	}
142 
143 	for (int i = 0; i < _ARGS_COUNT; i++) {
144 		args[i].f = fopen(args[i].fn, args[i].mode);
145 		if (!args[i].f) {
146 			fprintf(stderr, "ERROR: Can't open %s: %m\n",
147 				args[i].fn);
148 			goto err;
149 		}
150 	}
151 
152 	fprintf(args[ARGS_CHEADER].f, HEADER, args[ARGS_INPUT].fn);
153 	ret = parse(args[ARGS_INPUT].f, args[ARGS_CSOURCE].f,
154 		    args[ARGS_CHEADER].f);
155 	if (!ret)
156 		fprintf(args[ARGS_CHEADER].f, FOOTER);
157 
158 err:
159 	for (int i = 0; i < _ARGS_COUNT; i++) {
160 		if (args[i].f)
161 			fclose(args[i].f);
162 	}
163 
164 	return ret;
165 }
166