xref: /aosp_15_r20/external/coreboot/util/vgabios/testbios.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <sys/io.h>
7 #include <sys/mman.h>
8 #include <fcntl.h>
9 #include <getopt.h>
10 #include <string.h>
11 #include <stdarg.h>
12 #include <stdtypes.h>
13 #define die(x) { perror(x); exit(1); }
14 #define warn(x) { perror(x);  }
15 
16 #include <x86emu/x86emu.h>
17 #include <console/console.h>
18 #include <arch/byteorder.h>
19 #include "device.h"
20 
21 #include "testbios.h"
22 #include "pci-userspace.h"
23 int X86EMU_set_debug(int debug);
24 
25 biosemu_device_t bios_device;
26 
27 extern int teststart, testend;
28 
29 #define BIOSMEM_SIZE (1024 * 1024)
30 unsigned char biosmem[BIOSMEM_SIZE];
31 
32 int verbose = 0;
33 
mapitin(char * file,off_t where,size_t size)34 static unsigned char *mapitin(char *file, off_t where, size_t size)
35 {
36 	void *z;
37 
38 	int fd = open(file, O_RDWR, 0);
39 
40 	if (fd < 0)
41 		die(file);
42 	z = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, where);
43 	if (z == (void *) -1)
44 		die("mmap");
45 	close(fd);
46 
47 	return z;
48 }
49 
get_device(char * arg_val)50 static unsigned short get_device(char *arg_val)
51 {
52 	unsigned short devfn=0;
53 	long bus=0,dev=0,fn=0,need_pack=0;
54 	char *tok;
55 
56 	tok = strsep(&arg_val,":");
57 	if (arg_val != NULL) {
58 		bus = strtol(tok,0,16);
59 		need_pack = 1;
60 	}
61 	else {
62 		arg_val = tok;
63 	}
64 
65 	tok = strsep(&arg_val,".");
66 	if (arg_val != NULL) {
67 		dev = strtol(tok,0,16);
68 		fn  = strtol(arg_val,0,16);
69 		need_pack = 1;
70 	}
71 	else {
72 		if (need_pack ==1 && (strlen(tok))) {
73 			dev = strtol(tok,0,16);
74 		}
75 	}
76 
77 	if ( need_pack == 1) {
78 		devfn = bus<<8 | (dev<<3) | fn;
79 	}
80 	else {
81 		devfn = strtol(tok, 0, 0);
82 	}
83 
84 	return devfn;
85 }
86 
printk(int msg_level,const char * fmt,...)87 int printk(int msg_level, const char *fmt, ...)
88 {
89 	va_list args;
90 	int i;
91 
92 	putchar('<');
93 	putchar('0' + msg_level);
94 	putchar('>');
95 	putchar(' ');
96 	va_start(args, fmt);
97 	i = vprintf(fmt, args);
98 	va_end(args);
99 
100 	return i;
101 }
102 
usage(char * name)103 static void usage(char *name)
104 {
105 	printf
106 	    ("Usage: %s [-c codesegment] [-s size] [-b base] [-i ip] [-t] "
107 	     "<filename> ...\n", name);
108 }
109 
110 /* main entry into YABEL biosemu, arguments are:
111  * *biosmem = pointer to virtual memory
112  * biosmem_size = size of the virtual memory
113  * *dev = pointer to the device to be initialised
114  * rom_addr = address of the OptionROM to be executed, if this is = 0, YABEL
115  * will look for an ExpansionROM BAR and use the code from there.
116  */
117 u32
118 biosemu(u8 *biosmem, u32 biosmem_size, struct device * dev, unsigned long
119 		rom_addr);
120 
121 
main(int argc,char ** argv)122 int main(int argc, char **argv)
123 {
124 	int ret;
125 	char *absegname = NULL;
126 	void *abseg = NULL;
127 	int c, trace = 0;
128 	unsigned char *cp;
129 	char *filename;
130 	ssize_t size = 0;
131 	int base = 0;
132 	int have_size = 0, have_base = 0, have_ip = 0, have_cs = 0;
133 	int have_devfn = 0;
134 	int parse_rom = 0;
135 	//char *fsegname = 0;
136 	//unsigned char *fsegptr;
137 	unsigned short initialip = 0, initialcs = 0, devfn = 0;
138 	//X86EMU_intrFuncs intFuncs[256];
139 	int debugflag = 0;
140 	struct device *dev;
141 
142 	//const char *optstring = "vh?b:i:c:s:tpd:";
143 	const char *optstring = "vh?b:i:c:s:tpd:";
144 	while (1) {
145 		int option_index = 0;
146 		static struct option long_options[] = {
147 			{"verbose", 0, 0, 'v'},
148 			{"help", 0, 0, 'h'},
149 			{"trace", 0, 0, 't'},
150 			{"base", 1, 0, 'b'},
151 			//{"fseg", 1, 0, 'f'},
152 			{"instructionpointer", 1, 0, 'i'},
153 			{"codesegment", 1, 0, 'c'},
154 			{"absegment", 1, 0, 'a'},
155 			{"size", 1, 0, 's'},
156 			{"parserom", 0, 0, 'p'},
157 			{"device", 1, 0, 'd'},
158 			{"debug", 1, 0, 'D'},
159 			{0, 0, 0, 0}
160 		};
161 		c = getopt_long(argc, argv, optstring, long_options, &option_index);
162 		if (c == -1)
163 			break;
164 		switch (c) {
165 		case 'v':
166 			verbose = 1;
167 			break;
168 		case 'h':
169 		case '?':
170 			usage(argv[0]);
171 			return 0;
172 		case 't':
173 			trace = 1;
174 			break;
175 		//case 'b':
176 		//	base = strtol(optarg, 0, 0);
177 		//	have_base = 1;
178 		//	break;
179 		case 'i':
180 			initialip = strtol(optarg, 0, 0);
181 			have_ip = 1;
182 			break;
183 		case 'c':
184 			initialcs = strtol(optarg, 0, 0);
185 			have_cs = 1;
186 			break;
187 		case 's':
188 			size = strtol(optarg, 0, 0);
189 			have_size = 1;
190 			break;
191 		case 'p':
192 			parse_rom = 1;
193 			break;
194 	//	case 'f':
195 	//		fsegname = optarg;
196 	//		break;
197 		case 'a':
198 			absegname = optarg;
199 			break;
200 		case 'd':
201 			devfn = get_device(optarg);
202 			have_devfn = 1;
203 			break;
204 		case 'D':
205 			debugflag = strtol(optarg, 0, 0);
206 			break;
207 		default:
208 			printf("Unknown option\n");
209 			usage(argv[0]);
210 			return 1;
211 		}
212 	}
213 
214 	if (optind >= argc) {
215 		printf("Filename missing.\n");
216 		usage(argv[0]);
217 		return 1;
218 	}
219 
220 	while (optind < argc) {
221 		printf("running file %s\n", argv[optind]);
222 		filename = argv[optind];
223 		optind++;
224 		/* normally we would do continue, but for
225 		 * now only one filename is supported.
226 		 */
227 		/* continue; */
228 		break;
229 	}
230 
231 	if (!have_size) {
232 		printf("No size specified. defaulting to 32k\n");
233 		size = 32 * 1024;
234 	}
235 	if (!have_base) {
236 		printf("No base specified. defaulting to 0xc0000\n");
237 		base = 0xc0000;
238 	}
239 	//if (!have_cs) {
240 	//	printf("No initial code segment specified. defaulting to 0xc000\n");
241 	//	initialcs = 0xc000;
242 	//}
243 	if (!have_ip) {
244 		printf
245 		    ("No initial instruction pointer specified. defaulting to 0x0003\n");
246 		initialip = 0x0003;
247 	}
248 
249 	if (parse_rom)
250 		printf("Parsing rom images not implemented.\n");
251 
252 	//printf("Point 1 int%x vector at %x\n", 0x42, getIntVect(0x42));
253 #if 0
254 	if (initialip == 0x0003) {
255 		if ((devfn == 0) || (have_devfn == 0)) {
256 			printf("WARNING! It appears you are trying to run an option ROM.\n");
257 			printf("  (initial ip = 0x0003)\n");
258 			if (have_devfn) {
259 				printf("  However, the device you have specified is 0x00\n");
260 				printf("  It is very unlikely that your device is at this address\n");
261 				printf("  Please check your -d option\n");
262 			}
263 			else {
264 				printf("  Please specify a device with -d\n");
265 				printf("  The default is not likely to work\n");
266 			}
267 		}
268 	}
269 #endif
270 
271 	if (absegname) {
272 		abseg = mapitin(absegname, (off_t) 0xa0000, 0x20000);
273 		if (!abseg)
274 			die(absegname);
275 	}
276 
277 	ioperm(0, 0x400, 1);
278 
279 	if (iopl(3) < 0) {
280 		warn("iopl failed, continuing anyway");
281 	}
282 
283 	/* Emergency sync ;-) */
284 	sync();
285 	sync();
286 
287 	/* Setting up interrupt environment.
288 	 * basically this means initializing PCI and
289 	 * intXX handlers.
290 	 */
291 	pci_initialize();
292 
293 #if 0
294 	for (i = 0; i < 256; i++)
295 		intFuncs[i] = do_int;
296 	X86EMU_setupIntrFuncs(intFuncs);
297 #endif
298 	cp = mapitin(filename, (off_t) 0, size);
299 
300 	if (devfn) {
301 		printf("Loading ax with BusDevFn = %x\n",devfn);
302 	}
303 
304 #if 0
305 	current->ax = devfn   ? devfn : 0xff;
306 	current->dx = 0x80;
307 	//      current->ip = 0;
308 	for (i = 0; i < size; i++)
309 		wrb(base + i, cp[i]);
310 
311 	if (fsegname) {
312 		fsegptr = mapitin(fsegname, (off_t) 0, 0x10000);
313 		for (i = 0; i < 0x10000; i++)
314 			wrb(0xf0000 + i, fsegptr[i]);
315 	} else {
316 		const char *date = "01/01/99";
317 		for (i = i; date[i]; i++)
318 			wrb(0xffff5 + i, date[i]);
319 		wrb(0xffff7, '/');
320 		wrb(0xffffa, '/');
321 	}
322 	/* cpu setup */
323 	X86_AX = devfn ? devfn : 0xff;
324 	X86_DX = 0x80;
325 	X86_EIP = initialip;
326 	X86_CS = initialcs;
327 
328 	/* Initialize stack and data segment */
329 	X86_SS = 0x0030;
330 	X86_DS = 0x0040;
331 	X86_SP = 0xfffe;
332 	/* We need a sane way to return from bios
333 	 * execution. A hlt instruction and a pointer
334 	 * to it, both kept on the stack, will do.
335 	 */
336 	pushw(0xf4f4);		/* hlt; hlt */
337 	pushw(X86_SS);
338 	pushw(X86_SP + 2);
339 
340 	X86_ES = 0x0000;
341 #endif
342 
343 	if (trace) {
344 		printf("Switching to single step mode.\n");
345 		//X86EMU_trace_on();
346 	}
347 	if (debugflag) {
348 		printf("Enable Debug = %x.\n",debugflag);
349 		//X86EMU_set_debug(debugflag);
350 	}
351 #if 0
352 	X86EMU_exec();
353 #endif
354 
355 	ret = biosemu(biosmem, BIOSMEM_SIZE, dev, base);
356 
357 #if 0
358 	current = &p;
359 	X86EMU_setMemBase(biosmem, sizeof(biosmem));
360 	M.abseg = (unsigned long)abseg;
361 	X86EMU_setupPioFuncs(&myfuncs);
362 #endif
363 
364 	/* Cleaning up */
365 	pci_exit();
366 
367 	return 0;
368 }
369