Add code for AmigaOne board
(preliminary merge to U-Boot, still WIP)
* Patch by Jon Diekema, 12 Nov 2002:
- Adding URL for IEEE OUI lookup
- Making the autoboot #defines dependent on CONFIG_AUTOBOOT_KEYED
being defined.
- In the CONFIG_EXTRA_ENV_SETTINGS #define, the root-on-initrd and
root-on-nfs macros are designed to switch how the default boot
method gets defined.
499 lines
17 KiB
Plaintext
499 lines
17 KiB
Plaintext
%{
|
|
#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,®s);
|
|
}
|
|
|
|
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;
|
|
}
|