1
2
3
4
5
6
7
8
9
10
11
12
13
14#ifdef COREBOOT_V2
15#include "compat/rtas.h"
16#else
17#include <rtas.h>
18#endif
19
20#include "biosemu.h"
21#include "mem.h"
22#include "device.h"
23#include "debug.h"
24#include "pmm.h"
25
26#include <x86emu/x86emu.h>
27#ifdef COREBOOT_V2
28#include "../x86emu/prim_ops.h"
29#else
30#include <x86emu/prim_ops.h>
31#endif
32
33#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
34#include <device/pci.h>
35#include <device/pci_ops.h>
36#endif
37
38
39
40void
41setupInt(int intNum)
42{
43 DEBUG_PRINTF_INTR("%s(%x): executing interrupt handler @%08x\n",
44 __func__, intNum, my_rdl(intNum * 4));
45
46 push_word((u16) M.x86.R_FLG);
47 CLEAR_FLAG(F_IF);
48 CLEAR_FLAG(F_TF);
49
50 push_word(M.x86.R_CS);
51 push_word(M.x86.R_IP);
52
53
54 M.x86.R_CS = my_rdw(intNum * 4 + 2);
55 M.x86.R_IP = my_rdw(intNum * 4);
56}
57
58
59void
60handleInt10(void)
61{
62
63
64
65
66
67
68
69
70 switch (M.x86.R_AH) {
71 case 0x00:
72
73
74 my_wrb(0x449, M.x86.R_AL);
75 if (M.x86.R_AL > 7)
76 M.x86.R_AL = 0x20;
77 else if (M.x86.R_AL == 6)
78 M.x86.R_AL = 0x3f;
79 else
80 M.x86.R_AL = 0x30;
81 break;
82 case 0x01:
83
84
85 break;
86 case 0x02:
87
88
89
90
91 my_wrw(0x450 + (M.x86.R_BH * 2), M.x86.R_DX);
92 break;
93 case 0x03:
94
95
96
97
98 M.x86.R_AX = 0;
99 M.x86.R_CH = 0;
100 M.x86.R_CL = 0;
101 M.x86.R_DX = my_rdw(0x450 + (M.x86.R_BH * 2));
102 break;
103 case 0x05:
104
105
106 my_wrb(0x462, M.x86.R_AL);
107 break;
108 case 0x06:
109
110 break;
111 case 0x07:
112
113 break;
114 case 0x08:
115
116 M.x86.R_AH = 0x07;
117 M.x86.R_AL = 0x20;
118 break;
119 case 0x09:
120
121
122
123 CHECK_DBG(DEBUG_PRINT_INT10) {
124 u32 i = 0;
125 if (M.x86.R_BH == my_rdb(0x462)) {
126 for (i = 0; i < M.x86.R_CX; i++)
127 printf("%c", M.x86.R_AL);
128 }
129 }
130 break;
131 case 0x0a:
132
133
134
135 CHECK_DBG(DEBUG_PRINT_INT10) {
136 u32 i = 0;
137 if (M.x86.R_BH == my_rdb(0x462)) {
138 for (i = 0; i < M.x86.R_CX; i++)
139 printf("%c", M.x86.R_AL);
140 }
141 }
142 break;
143 case 0x0e:
144
145
146
147 CHECK_DBG(DEBUG_PRINT_INT10) {
148
149
150 {
151 printf("%c", M.x86.R_AL);
152
153
154
155 }
156 }
157 break;
158 case 0x0f:
159
160
161
162
163 M.x86.R_AH = 80;
164 M.x86.R_AL = my_rdb(0x449);
165 M.x86.R_BH = my_rdb(0x462);
166 break;
167 default:
168 printf("%s(): unknown function (%x) for int10 handler.\n",
169 __func__, M.x86.R_AH);
170 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
171 M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
172 M.x86.R_DX);
173 HALT_SYS();
174 break;
175 }
176}
177
178
179static u8 keycode_table[256] = {
180 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
184 0x39, 0x02, 0x28, 0x04, 0x05, 0x06, 0x08, 0x28,
185 0x0a, 0x0b, 0x09, 0x2b, 0x33, 0x0d, 0x34, 0x35,
186 0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
187 0x09, 0x0a, 0x27, 0x27, 0x33, 0x2b, 0x34, 0x35,
188 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
189 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
192 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
194 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
195 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
201 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
202 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
203 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
204 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
206 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
207 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
210 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
212}
213
214;
215
216void
217translate_keycode(u64 * keycode)
218{
219 u8 scan_code = 0;
220 u8 char_code = 0;
221 if (*keycode < 256) {
222 scan_code = keycode_table[*keycode];
223 char_code = (u8) * keycode & 0xff;
224 } else {
225 switch (*keycode) {
226 case 0x1b50:
227
228 scan_code = 0x3b;
229 char_code = 0x0;
230 break;
231 default:
232 printf("%s(): unknown multibyte keycode: %llx\n",
233 __func__, *keycode);
234 break;
235 }
236 }
237
238 *keycode = (u64) ((((u16) scan_code) << 8) | char_code);
239}
240
241
242void
243handleInt16(void)
244{
245
246
247
248
249
250
251
252
253 u64 *keycode = (u64 *) (M.mem_base + 0x41e);
254 s8 c;
255
256 DEBUG_PRINTF_INTR("%s(): Keyboard Interrupt: function: %x.\n",
257 __func__, M.x86.R_AH);
258 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n", M.x86.R_AX,
259 M.x86.R_BX, M.x86.R_CX, M.x86.R_DX);
260 switch (M.x86.R_AH) {
261 case 0x00:
262
263 if (*keycode) {
264 M.x86.R_AX = (u16) * keycode;
265
266 *keycode = 0;
267 } else {
268 M.x86.R_AH = 0x61;
269 M.x86.R_AL = 0x20;
270 }
271 break;
272 case 0x01:
273
274
275
276 if (*keycode) {
277
278 CLEAR_FLAG(F_ZF);
279 M.x86.R_AX = (u16) * keycode;
280 } else {
281
282 c = -1;
283 if (c == -1) {
284
285 SET_FLAG(F_ZF);
286 } else {
287 *keycode = c;
288
289
290
291
292
293 printf("tt%c%c", 0x08, 0x08);
294
295
296 while ((c = -1 ) != -1) {
297 *keycode = (*keycode << 8) | c;
298 DEBUG_PRINTF(" key read: %0llx\n",
299 *keycode);
300 }
301 translate_keycode(keycode);
302 DEBUG_PRINTF(" translated key: %0llx\n",
303 *keycode);
304 if (*keycode == 0) {
305
306 SET_FLAG(F_ZF);
307 } else {
308 CLEAR_FLAG(F_ZF);
309 M.x86.R_AX = (u16) * keycode;
310
311
312 }
313 }
314 }
315 break;
316 default:
317 printf("%s(): unknown function (%x) for int16 handler.\n",
318 __func__, M.x86.R_AH);
319 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
320 M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
321 M.x86.R_DX);
322 HALT_SYS();
323 break;
324 }
325}
326
327
328void
329handleInt1a(void)
330{
331
332 u8 bus, devfn, offs;
333 struct device* dev;
334 switch (M.x86.R_AX) {
335 case 0xb101:
336
337 CLEAR_FLAG(F_CF);
338 M.x86.R_EDX = 0x20494350;
339 M.x86.R_AL = 0x1;
340 M.x86.R_BX = 0x0210;
341 M.x86.R_CL = 0xff;
342 break;
343 case 0xb102:
344
345
346
347
348
349 DEBUG_PRINTF_INTR("%s(): function: %x: PCI Find Device\n",
350 __func__, M.x86.R_AX);
351
352#if defined(CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES) && CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES==1
353#ifdef COREBOOT_V2
354 dev = dev_find_device(M.x86.R_DX, M.x86.R_CX, 0);
355#else
356 dev = dev_find_pci_device(M.x86.R_DX, M.x86.R_CX, 0);
357#endif
358 if (dev != 0) {
359 DEBUG_PRINTF_INTR
360 ("%s(): function %x: PCI Find Device --> 0x%04x\n",
361 __func__, M.x86.R_AX, M.x86.R_BX);
362
363 M.x86.R_BH = dev->bus->secondary;
364 M.x86.R_BL = dev->path.pci.devfn;
365 M.x86.R_AH = 0x00;
366 CLEAR_FLAG(F_CF);
367#else
368
369 if ((M.x86.R_CX == bios_device.pci_device_id)
370 && (M.x86.R_DX == bios_device.pci_vendor_id)
371
372 && (M.x86.R_SI == 0)) {
373 CLEAR_FLAG(F_CF);
374 M.x86.R_AH = 0x00;
375 M.x86.R_BH = bios_device.bus;
376 M.x86.R_BL = bios_device.devfn;
377#endif
378 } else {
379 DEBUG_PRINTF_INTR
380 ("%s(): function %x: invalid device/vendor/device index! (%04x/%04x/%02x expected: %04x/%04x/00) \n",
381 __func__, M.x86.R_AX, M.x86.R_CX, M.x86.R_DX,
382 M.x86.R_SI, bios_device.pci_device_id,
383 bios_device.pci_vendor_id);
384
385 SET_FLAG(F_CF);
386 M.x86.R_AH = 0x86;
387 }
388 break;
389 case 0xb108:
390 case 0xb109:
391 case 0xb10a:
392 bus = M.x86.R_BH;
393 devfn = M.x86.R_BL;
394 offs = M.x86.R_DI;
395 DEBUG_PRINTF_INTR("%s(): function: %x: PCI Config Read from device: bus: %02x, devfn: %02x, offset: %02x\n",
396 __func__, M.x86.R_AX, bus, devfn, offs);
397#if defined(CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES) && CONFIG_YABEL_PCI_ACCESS_OTHER_DEVICES==1
398 dev = dev_find_slot(bus, devfn);
399 DEBUG_PRINTF_INTR("%s(): function: %x: dev_find_slot() returned: %s\n",
400 __func__, M.x86.R_AX, dev_path(dev));
401 if (dev == 0) {
402
403#else
404 dev = bios_device.dev;
405 if ((bus != bios_device.bus)
406 || (devfn != bios_device.devfn)) {
407
408#endif
409 printf
410 ("%s(): Config read access invalid device! bus: %02x (%02x), devfn: %02x (%02x), offs: %02x\n",
411 __func__, bus, bios_device.bus, devfn,
412 bios_device.devfn, offs);
413 SET_FLAG(F_CF);
414 M.x86.R_AH = 0x87;
415 HALT_SYS();
416 return;
417 } else {
418 switch (M.x86.R_AX) {
419 case 0xb108:
420 M.x86.R_CL =
421#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
422 pci_read_config8(dev, offs);
423#else
424 (u8) rtas_pci_config_read(bios_device.
425 puid, 1,
426 bus, devfn,
427 offs);
428#endif
429 DEBUG_PRINTF_INTR
430 ("%s(): function %x: PCI Config Read @%02x --> 0x%02x\n",
431 __func__, M.x86.R_AX, offs,
432 M.x86.R_CL);
433 break;
434 case 0xb109:
435 M.x86.R_CX =
436#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
437 pci_read_config16(dev, offs);
438#else
439 (u16) rtas_pci_config_read(bios_device.
440 puid, 2,
441 bus, devfn,
442 offs);
443#endif
444 DEBUG_PRINTF_INTR
445 ("%s(): function %x: PCI Config Read @%02x --> 0x%04x\n",
446 __func__, M.x86.R_AX, offs,
447 M.x86.R_CX);
448 break;
449 case 0xb10a:
450 M.x86.R_ECX =
451#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
452 pci_read_config32(dev, offs);
453#else
454 (u32) rtas_pci_config_read(bios_device.
455 puid, 4,
456 bus, devfn,
457 offs);
458#endif
459 DEBUG_PRINTF_INTR
460 ("%s(): function %x: PCI Config Read @%02x --> 0x%08x\n",
461 __func__, M.x86.R_AX, offs,
462 M.x86.R_ECX);
463 break;
464 }
465 CLEAR_FLAG(F_CF);
466 M.x86.R_AH = 0x0;
467 }
468 break;
469 case 0xb10b:
470 case 0xb10c:
471 case 0xb10d:
472 bus = M.x86.R_BH;
473 devfn = M.x86.R_BL;
474 offs = M.x86.R_DI;
475 if ((bus != bios_device.bus)
476 || (devfn != bios_device.devfn)) {
477
478 printf
479 ("%s(): Config read access invalid! bus: %x (%x), devfn: %x (%x), offs: %x\n",
480 __func__, bus, bios_device.bus, devfn,
481 bios_device.devfn, offs);
482 SET_FLAG(F_CF);
483 M.x86.R_AH = 0x87;
484 HALT_SYS();
485 return;
486 } else {
487 switch (M.x86.R_AX) {
488 case 0xb10b:
489#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
490 pci_write_config8(bios_device.dev, offs, M.x86.R_CL);
491#else
492 rtas_pci_config_write(bios_device.puid, 1, bus,
493 devfn, offs, M.x86.R_CL);
494#endif
495 DEBUG_PRINTF_INTR
496 ("%s(): function %x: PCI Config Write @%02x <-- 0x%02x\n",
497 __func__, M.x86.R_AX, offs,
498 M.x86.R_CL);
499 break;
500 case 0xb10c:
501#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
502 pci_write_config16(bios_device.dev, offs, M.x86.R_CX);
503#else
504 rtas_pci_config_write(bios_device.puid, 2, bus,
505 devfn, offs, M.x86.R_CX);
506#endif
507 DEBUG_PRINTF_INTR
508 ("%s(): function %x: PCI Config Write @%02x <-- 0x%04x\n",
509 __func__, M.x86.R_AX, offs,
510 M.x86.R_CX);
511 break;
512 case 0xb10d:
513#ifdef CONFIG_PCI_OPTION_ROM_RUN_YABEL
514 pci_write_config32(bios_device.dev, offs, M.x86.R_ECX);
515#else
516 rtas_pci_config_write(bios_device.puid, 4, bus,
517 devfn, offs, M.x86.R_ECX);
518#endif
519 DEBUG_PRINTF_INTR
520 ("%s(): function %x: PCI Config Write @%02x <-- 0x%08x\n",
521 __func__, M.x86.R_AX, offs,
522 M.x86.R_ECX);
523 break;
524 }
525 CLEAR_FLAG(F_CF);
526 M.x86.R_AH = 0x0;
527 }
528 break;
529 default:
530 printf("%s(): unknown function (%x) for int1a handler.\n",
531 __func__, M.x86.R_AX);
532 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
533 M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
534 M.x86.R_DX);
535 HALT_SYS();
536 break;
537 }
538}
539
540
541void
542handleInterrupt(int intNum)
543{
544 u8 int_handled = 0;
545#ifndef DEBUG_PRINT_INT10
546
547
548 DEBUG_PRINTF_INTR("%s(%x)\n", __func__, intNum);
549#endif
550
551
552 if (yabel_intFuncArray[intNum]) {
553 DEBUG_PRINTF_INTR("%s(%x) intHandler overridden, calling it...\n", __func__, intNum);
554 int_handled = (*yabel_intFuncArray[intNum])();
555 } else {
556 switch (intNum) {
557 case 0x10:
558 case 0x42:
559 case 0x6d:
560
561 if ((my_rdl(intNum * 4) == 0xF000F065) ||
562 (my_rdl(intNum * 4) == 0xF4F4F4F4))
563 {
564#if 0
565
566 DEBUG_PRINTF_INTR
567 ("%s(%x): invalid interrupt Vector (%08x) found, interrupt ignored...\n",
568 __func__, intNum, my_rdl(intNum * 4));
569 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
570 M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
571 M.x86.R_DX);
572
573#endif
574 handleInt10();
575 int_handled = 1;
576 }
577 break;
578 case 0x16:
579
580 handleInt16();
581 int_handled = 1;
582 break;
583 case 0x1a:
584
585 handleInt1a();
586 int_handled = 1;
587 break;
588 case PMM_INT_NUM:
589
590
591
592 pmm_handleInt();
593 int_handled = 1;
594 break;
595 default:
596 printf("Interrupt %#x (Vector: %x) not implemented\n", intNum,
597 my_rdl(intNum * 4));
598 DEBUG_PRINTF_INTR("AX=%04x BX=%04x CX=%04x DX=%04x\n",
599 M.x86.R_AX, M.x86.R_BX, M.x86.R_CX,
600 M.x86.R_DX);
601 int_handled = 1;
602 HALT_SYS();
603 break;
604 }
605 }
606
607 if (!int_handled) {
608 setupInt(intNum);
609 }
610}
611
612
613void
614runInt10(void)
615{
616
617 M.x86.R_SS = STACK_SEGMENT;
618 M.x86.R_DS = DATA_SEGMENT;
619 M.x86.R_SP = STACK_START_OFFSET;
620
621
622
623
624 push_word(0xf4f4);
625
626
627
628
629
630
631 M.x86.R_CS = M.x86.R_SS;
632 M.x86.R_IP = M.x86.R_SP;
633
634 CHECK_DBG(DEBUG_TRACE_X86EMU) {
635 X86EMU_trace_on();
636 }
637 CHECK_DBG(DEBUG_JMP) {
638 M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
639 M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
640 M.x86.debug |= DEBUG_TRACECALL_F;
641 M.x86.debug |= DEBUG_TRACECALL_REGS_F;
642 }
643 setupInt(0x10);
644 DEBUG_PRINTF_INTR("%s(): starting execution of INT10...\n",
645 __func__);
646 X86EMU_exec();
647 DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
648}
649
650
651void
652runInt13(void)
653{
654
655 M.x86.R_SS = STACK_SEGMENT;
656 M.x86.R_DS = DATA_SEGMENT;
657 M.x86.R_SP = STACK_START_OFFSET;
658
659
660
661
662 push_word(0xf4f4);
663
664
665
666
667
668
669 M.x86.R_CS = M.x86.R_SS;
670 M.x86.R_IP = M.x86.R_SP;
671
672 CHECK_DBG(DEBUG_TRACE_X86EMU) {
673 X86EMU_trace_on();
674 }
675 CHECK_DBG(DEBUG_JMP) {
676 M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
677 M.x86.debug |= DEBUG_TRACEJMP_REGS_F;
678 M.x86.debug |= DEBUG_TRACECALL_F;
679 M.x86.debug |= DEBUG_TRACECALL_REGS_F;
680 }
681
682 setupInt(0x13);
683 DEBUG_PRINTF_INTR("%s(): starting execution of INT13...\n",
684 __func__);
685 X86EMU_exec();
686 DEBUG_PRINTF_INTR("%s(): execution finished\n", __func__);
687}
688