summaryrefslogtreecommitdiffstats
path: root/board/MAI/bios_emulator/scitech/src/v86bios/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'board/MAI/bios_emulator/scitech/src/v86bios/parser.y')
-rw-r--r--board/MAI/bios_emulator/scitech/src/v86bios/parser.y498
1 files changed, 498 insertions, 0 deletions
diff --git a/board/MAI/bios_emulator/scitech/src/v86bios/parser.y b/board/MAI/bios_emulator/scitech/src/v86bios/parser.y
new file mode 100644
index 0000000000..21c4023dcd
--- /dev/null
+++ b/board/MAI/bios_emulator/scitech/src/v86bios/parser.y
@@ -0,0 +1,498 @@
+%{
+#include <malloc.h>
+#include <string.h>
+#include "v86bios.h"
+#include "pci.h"
+
+#define YYSTYPE unsigned long
+
+#define MAX_VAR 0x20
+
+ CARD32 var[MAX_VAR];
+ CARD32 var_mem;
+
+
+i86biosRegs regs = { 00 };
+
+enum mem_type { BYTE, WORD, LONG, STRING };
+union mem_val {
+ CARD32 integer;
+ char *ptr;
+} rec;
+
+struct mem {
+ enum mem_type type;
+ union mem_val val;
+ struct mem *next;
+};
+
+
+struct device Device = {FALSE,NONE,{0}};
+
+extern void yyerror(char *s);
+extern int yylex( void );
+
+static void boot(void);
+static void dump_mem(CARD32 addr, int len);
+static void exec_int(int num);
+static void *add_to_list(enum mem_type type, union mem_val *rec, void *next);
+static void do_list(struct mem *list, memType addr);
+static char * normalize_string(char *ptr);
+%}
+
+%token TOK_NUM
+%token TOK_REG_AX
+%token TOK_REG_BX
+%token TOK_REG_CX
+%token TOK_REG_DX
+%token TOK_REG_DI
+%token TOK_REG_SI
+%token TOK_SEG_DS
+%token TOK_SEG_ES
+%token TOK_SEP
+%token TOK_VAR
+%token TOK_VAR_MEM
+%token TOK_COMMAND_BOOT
+%token TOK_COMMAND_EXEC
+%token TOK_SELECT
+%token TOK_STRING
+%token TOK_MODIFIER_BYTE
+%token TOK_MODIFIER_WORD
+%token TOK_MODIFIER_LONG
+%token TOK_MODIFIER_MEMSET
+%token TOK_COMMAND_MEMSET
+%token TOK_COMMAND_MEMDUMP
+%token TOK_COMMAND_QUIT
+%token TOK_ERROR
+%token TOK_END
+%token TOK_ISA
+%token TOK_PCI
+%token TOK_BYTE
+%token TOK_WORD
+%token TOK_LONG
+%token TOK_PRINT_PORT
+%token TOK_IOSTAT
+%token TOK_PRINT_IRQ
+%token TOK_PPCI
+%token TOK_PIP
+%token TOK_TRACE
+%token TOK_ON
+%token TOK_OFF
+%token TOK_VERBOSE
+%token TOK_LOG
+%token TOK_LOGOFF
+%token TOK_CLSTAT
+%token TOK_STDOUT
+%token TOK_HLT
+%token TOK_DEL
+%token TOK_IOPERM
+%token TOK_DUMP_PCI
+%token TOK_BOOT_BIOS
+%%
+input: | input line
+line: end | com_reg | com_var | com_select
+ | com_boot | com_memset | com_memdump | com_quit
+ | com_exec | hlp | config | verbose | logging | print | clstat
+ | com_hlt | ioperm | list_pci | boot_bios
+ | error end { printf("unknown command\n"); }
+;
+end: TOK_END
+;
+com_reg: reg_off val end { *(CARD16*)$1 = $2 & 0xffff; }
+ | reg_seg TOK_SEP reg_off val end {
+ *(CARD16*)$1 = ($4 & 0xf0000) >> 4;
+ *(CARD16*)$3 = ($4 & 0x0ffff);
+ }
+ | reg_off '?' end { printf("0x%x\n",*(CARD16*)$1);}
+ | reg_seg TOK_SEP reg_off '?' end
+ { printf("0x%x:0x%x\n",*(CARD16*)$1,
+ *(CARD16*)$3); }
+;
+register_read: reg_seg TOK_SEP reg_off { $$ = (((*(CARD16*)$1) << 4)
+ | ((*(CARD16*)$3) & 0xffff));
+ }
+ | reg_off { $$ = ((*(CARD16*)$1) & 0xffff); }
+;
+reg_off: TOK_REG_AX { $$ = (unsigned long)&(regs.ax); }
+ | TOK_REG_BX { $$ = (unsigned long)&(regs.bx); }
+ | TOK_REG_CX { $$ = (unsigned long)&(regs.cx); }
+ | TOK_REG_DX { $$ = (unsigned long)&(regs.dx); }
+ | TOK_REG_DI { $$ = (unsigned long)&(regs.di); }
+ | TOK_REG_SI { $$ = (unsigned long)&(regs.si); }
+;
+reg_seg: TOK_SEG_DS { $$ = (unsigned long)&(regs.ds); }
+ | TOK_SEG_ES { $$ = (unsigned long)&(regs.es); }
+;
+com_var: TOK_VAR_MEM '?' end { printf("var mem: 0x%x\n",var_mem); }
+ | TOK_VAR '?' end { if ($1 < MAX_VAR)
+ printf("var[%i]: 0x%x\n",(int)$1,var[$1]);
+ else
+ printf("var index %i out of range\n",(int)$1); }
+ | TOK_VAR_MEM val end { var_mem = $2; }
+ | TOK_VAR val end { if ($1 <= MAX_VAR)
+ var[$1] = $2;
+ else
+ printf("var index %i out of range\n",(int)$1); }
+ | TOK_VAR error end { printf("$i val\n"); }
+ | TOK_VAR_MEM error end { printf("$i val\n"); }
+;
+com_boot: TOK_COMMAND_BOOT end { boot(); }
+ TOK_COMMAND_BOOT error end { boot(); }
+;
+com_select: TOK_SELECT TOK_ISA end { Device.booted = FALSE;
+ Device.type = ISA;
+ CurrentPci = NULL; }
+ | TOK_SELECT TOK_PCI val TOK_SEP val TOK_SEP val end
+ { Device.booted = FALSE;
+ Device.type = PCI;
+ Device.loc.pci.bus = $3;
+ Device.loc.pci.dev = $5;
+ Device.loc.pci.func = $7; }
+ | TOK_SELECT '?' end
+ { switch (Device.type) {
+ case ISA:
+ printf("isa\n");
+ break;
+ case PCI:
+ printf("pci: %x:%x:%x\n",Device.loc.pci.bus,
+ Device.loc.pci.dev,
+ Device.loc.pci.func);
+ break;
+ default:
+ printf("no device selected\n");
+ break;
+ }
+ }
+ | TOK_SELECT error end { printf("select ? | isa "
+ "| pci:bus:dev:func\n"); }
+;
+com_quit: TOK_COMMAND_QUIT end { return 0; }
+ | TOK_COMMAND_QUIT error end { logoff(); return 0; }
+;
+com_exec: TOK_COMMAND_EXEC end { exec_int(0x10); }
+ | TOK_COMMAND_EXEC val end { exec_int($2); }
+ | TOK_COMMAND_EXEC error end { exec_int(0x10); }
+;
+com_memdump: TOK_COMMAND_MEMDUMP val val end { dump_mem($2,$3); }
+ | TOK_COMMAND_MEMDUMP error end { printf("memdump start len\n"); }
+
+
+;
+com_memset: TOK_COMMAND_MEMSET val list end { do_list((struct mem*)$3,$2);}
+ | TOK_COMMAND_MEMSET error end { printf("setmem addr [byte val] "
+ "[word val] [long val] "
+ "[\"string\"]\n"); }
+;
+list: { $$ = 0; }
+ | TOK_BYTE val list { rec.integer = $2;
+ $$ = (unsigned long)add_to_list(BYTE,&rec,(void*)$3); }
+ | TOK_WORD val list { rec.integer = $2;
+ $$ = (unsigned long) add_to_list(WORD,&rec,(void*)$3); }
+ | TOK_LONG val list { rec.integer = $2;
+ $$ = (unsigned long) add_to_list(LONG,&rec,(void*)$3); }
+ | TOK_STRING list { rec.ptr = (void*)$1;
+ $$ = (unsigned long) add_to_list(STRING,&rec,(void*)$2); }
+;
+val: TOK_VAR { if ($1 > MAX_VAR) {
+ printf("variable index out of range\n");
+ $$=0;
+ } else
+ $$ = var[$1]; }
+ | TOK_NUM { $$ = $1; }
+ | register_read
+;
+bool: TOK_ON { $$ = 1; }
+ | TOK_OFF { $$ = 0; }
+;
+config: TOK_PRINT_PORT bool end { Config.PrintPort = $2; }
+ | TOK_PRINT_PORT '?' end { printf("print port %s\n",
+ Config.PrintPort?"on":"off"); }
+ | TOK_PRINT_PORT error end { printf("pport on | off | ?\n") }
+ | TOK_PRINT_IRQ bool end { Config.PrintIrq = $2; }
+ | TOK_PRINT_IRQ '?' end { printf("print irq %s\n",
+ Config.PrintIrq?"on":"off"); }
+ | TOK_PRINT_IRQ error end { printf("pirq on | off | ?\n") }
+ | TOK_PPCI bool end { Config.PrintPci = $2; }
+ | TOK_PPCI '?' end { printf("print PCI %s\n",
+ Config.PrintPci?"on":"off"); }
+ | TOK_PPCI error end { printf("ppci on | off | ?\n") }
+ | TOK_PIP bool end { Config.PrintIp = $2; }
+ | TOK_PIP '?' end { printf("printip %s\n",
+ Config.PrintIp?"on":"off"); }
+ | TOK_PIP error end { printf("pip on | off | ?\n") }
+ | TOK_IOSTAT bool end { Config.IoStatistics = $2; }
+ | TOK_IOSTAT '?' end { printf("io statistics %s\n",
+ Config.IoStatistics?"on":"off"); }
+ | TOK_IOSTAT error end { printf("iostat on | off | ?\n") }
+ | TOK_TRACE bool end { Config.Trace = $2; }
+ | TOK_TRACE '?' end { printf("trace %s\n",
+ Config.Trace ?"on":"off"); }
+ | TOK_TRACE error end { printf("trace on | off | ?\n") }
+;
+verbose: TOK_VERBOSE val end { Config.Verbose = $2; }
+ | TOK_VERBOSE '?' end { printf("verbose: %i\n",
+ Config.Verbose); }
+ | TOK_VERBOSE error end { printf("verbose val | ?\n"); }
+;
+logging: TOK_LOG TOK_STRING end { logon(normalize_string((char*)$2)); }
+ | TOK_LOG '?' end { if (logging) printf("logfile: %s\n",
+ logfile);
+ else printf("no logging\n?"); }
+ | TOK_LOG TOK_OFF end { logoff(); }
+ | TOK_LOG error end { printf("log \"<filename>\" | ? |"
+ " off\n"); }
+;
+clstat: TOK_CLSTAT end { clear_stat(); }
+ | TOK_CLSTAT error end { printf("clstat\n"); }
+;
+print: TOK_STDOUT bool end { nostdout = !$2; }
+ | TOK_STDOUT '?' end { printf("print %s\n",nostdout ?
+ "no":"yes"); }
+ | TOK_STDOUT error end { printf("print on | off\n"); }
+;
+com_hlt: TOK_HLT val end { add_hlt($2); }
+ | TOK_HLT TOK_DEL val end { del_hlt($3); }
+ | TOK_HLT TOK_DEL end { del_hlt(21); }
+ | TOK_HLT '?' end { list_hlt(); }
+ | TOK_HLT error end { printf(
+ "hlt val | del [val] | ?\n"); }
+;
+ioperm: TOK_IOPERM val val val end { int i,max;
+ if ($2 >= 0) {
+ max = $2 + $3 - 1;
+ if (max > IOPERM_BITS)
+ max = IOPERM_BITS;
+ for (i = $2;i <= max; i++)
+ ioperm_list[i]
+ = $4>0 ? 1 : 0;
+ }
+ }
+ | TOK_IOPERM '?' end { int i,start;
+ for (i=0; i <= IOPERM_BITS; i++) {
+ if (ioperm_list[i]) {
+ start = i;
+ for (; i <= IOPERM_BITS; i++)
+ if (!ioperm_list[i]) {
+ printf("ioperm on in "
+ "0x%x+0x%x\n", start,i-start);
+ break;
+ }
+ }
+ }
+ }
+ | TOK_IOPERM error end { printf("ioperm start len val\n"); }
+;
+list_pci: TOK_DUMP_PCI end { list_pci(); }
+ | TOK_DUMP_PCI error end { list_pci(); }
+;
+boot_bios: TOK_BOOT_BIOS '?' end { if (!BootBios) printf("No Boot BIOS\n");
+ else printf("BootBIOS from: %i:%i:%i\n",
+ BootBios->bus, BootBios->dev,
+ BootBios->func); }
+ | TOK_BOOT_BIOS error end { printf ("bootbios bus:dev:num\n"); }
+;
+hlp: '?' { printf("Command list:\n");
+ printf(" select isa | pci bus:dev:func\n");
+ printf(" boot\n");
+ printf(" seg:reg val | reg val \n");
+ printf(" $x val | $mem val\n");
+ printf(" setmem addr list; addr := val\n");
+ printf(" dumpmem addr len; addr,len := val\n");
+ printf(" do [val]\n");
+ printf(" quit\n");
+ printf(" ?\n");
+ printf(" seg := ds | es;"
+ " reg := ax | bx | cx | dx | si \n");
+ printf(" val := var | <hex-number> | seg:reg | seg\n");
+ printf(" var := $x | $mem; x := 0..20\n");
+ printf(" list := byte val | word val | long val "
+ "| \"string\"\n");
+ printf(" pport on | off | ?\n");
+ printf(" ppci on | off | ?\n");
+ printf(" pirq on | off | ?\n");
+ printf(" pip on | off | ?\n");
+ printf(" trace on | off | ?\n");
+ printf(" iostat on | off | ?\n");
+ printf(" verbose val\n");
+ printf(" log \"<filename>\" | off | ?\n");
+ printf(" print on | off\n");
+ printf(" hlt val | del [val] | ?\n");
+ printf(" clstat\n");
+ printf(" lpci\n");
+ printf ("bootbios ?\n");
+}
+;
+
+%%
+
+static void
+dump_mem(CARD32 addr, int len)
+{
+ dprint(addr,len);
+}
+
+static void
+exec_int(int num)
+{
+ if (num == 0x10) { /* video interrupt */
+ if (Device.type == NONE) {
+ CurrentPci = PciList;
+ while (CurrentPci) {
+ if (CurrentPci->active)
+ break;
+ CurrentPci = CurrentPci->next;
+ }
+ if (!CurrentPci)
+ Device.type = ISA;
+ else {
+ Device.type = PCI;
+ Device.loc.pci.dev = CurrentPci->dev;
+ Device.loc.pci.bus = CurrentPci->bus;
+ Device.loc.pci.func = CurrentPci->func;
+ }
+ }
+ if (Device.type != ISA) {
+ if (!Device.booted) {
+ if (!CurrentPci || (Device.type == PCI
+ && (!CurrentPci->active
+ && (Device.loc.pci.dev != CurrentPci->dev
+ || Device.loc.pci.bus != CurrentPci->bus
+ || Device.loc.pci.func != CurrentPci->func)))) {
+ printf("boot the device fist\n");
+ return;
+ }
+ }
+ } else
+ CurrentPci = NULL;
+ } else {
+ Device.booted = FALSE; /* we need this for sanity! */
+ }
+
+ runINT(num,&regs);
+}
+
+static void
+boot(void)
+{
+ if (Device.type == NONE) {
+ printf("select a device fist\n");
+ return;
+ }
+
+ call_boot(&Device);
+}
+
+static void *
+add_to_list(enum mem_type type, union mem_val *rec, void *next)
+{
+ struct mem *mem_rec = (struct mem *) malloc(sizeof(mem_rec));
+
+ mem_rec->type = type;
+ mem_rec->next = next;
+
+ switch (type) {
+ case BYTE:
+ case WORD:
+ case LONG:
+ mem_rec->val.integer = rec->integer;
+ break;
+ case STRING:
+ mem_rec->val.ptr = normalize_string(rec->ptr);
+ break;
+ }
+ return mem_rec;
+}
+
+static int
+validRange(int addr,int len)
+{
+ int end = addr + len;
+
+ if (addr < 0x1000 || end > 0xc0000)
+ return 0;
+ return 1;
+}
+
+static void
+do_list(struct mem *list, memType addr)
+{
+ struct mem *prev;
+ int len;
+
+ while (list) {
+ switch (list->type) {
+ case BYTE:
+ if (!validRange(addr,1)) goto error;
+ *(CARD8*)addr = list->val.integer;
+ addr =+ 1;
+ break;
+ case WORD:
+ if (!validRange(addr,2)) goto error;
+ *(CARD16*)addr = list->val.integer;
+ addr =+ 2;
+ break;
+ case LONG:
+ if (!validRange(addr,4)) goto error;
+ *(CARD32*)addr = list->val.integer;
+ addr =+ 4;
+ break;
+ case STRING:
+ len = strlen((char*)list->val.ptr);
+ if (!validRange(addr,len)) goto error;
+ memcpy((CARD8*)addr,(void*)list->val.ptr,len);
+ addr =+ len;
+ free(list->val.ptr);
+ break;
+ }
+ prev = list;
+ list = list->next;
+ free(prev);
+ continue;
+ error:
+ printf("address out of range\n");
+ while (list) {
+ prev = list;
+ list = list->next;
+ free(prev);
+ }
+ break;
+ }
+}
+
+static char *
+normalize_string(char *ptr)
+{
+ int i = 0, j = 0, c = 0, esc= 0;
+ int size;
+ char *mem_ptr;
+
+ size = strlen(ptr);
+ mem_ptr = malloc(size);
+ while (1) {
+ switch (*(ptr + i)) {
+ case '\\':
+ if (esc) {
+ *(mem_ptr + j++) = *(ptr + i);
+ esc = 0;
+ } else
+ esc = 1;
+ break;
+ case '\"':
+ if (esc) {
+ *(mem_ptr + j++) = *(ptr + i);
+ esc = 0;
+ } else
+ c++;
+ break;
+ default:
+ *(mem_ptr + j++) = *(ptr + i);
+ break;
+ }
+ if (c > 1) {
+ *(mem_ptr + j) = '\0';
+ break;
+ }
+ i++;
+ }
+ return mem_ptr;
+}
OpenPOWER on IntegriCloud