diff options
author | Stefan Reinauer <stepan@coreboot.org> | 2010-12-11 20:33:41 +0000 |
---|---|---|
committer | Stefan Reinauer <stepan@openbios.org> | 2010-12-11 20:33:41 +0000 |
commit | 8677a23d5b053d550f70246de9c7dc8fd4e2fbf9 (patch) | |
tree | d9a7c6042de85d623739e2679ba90c66aad2797f /src/arch/x86/llshell | |
parent | 198cb96387c457affa01696405ffaa4531e8e361 (diff) | |
download | coreboot-8677a23d5b053d550f70246de9c7dc8fd4e2fbf9.tar.xz |
After this has been brought up many times before, rename src/arch/i386 to
src/arch/x86.
Signed-off-by: Stefan Reinauer <stepan@coreboot.org>
Acked-by: Patrick Georgi <patrick@georgi-clan.de>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@6161 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/arch/x86/llshell')
-rw-r--r-- | src/arch/x86/llshell/console.inc | 340 | ||||
-rw-r--r-- | src/arch/x86/llshell/llshell.inc | 901 | ||||
-rw-r--r-- | src/arch/x86/llshell/pci.inc | 229 | ||||
-rw-r--r-- | src/arch/x86/llshell/ramtest.inc | 125 | ||||
-rw-r--r-- | src/arch/x86/llshell/readme.coreboot | 25 |
5 files changed, 1620 insertions, 0 deletions
diff --git a/src/arch/x86/llshell/console.inc b/src/arch/x86/llshell/console.inc new file mode 100644 index 0000000000..84f62e3448 --- /dev/null +++ b/src/arch/x86/llshell/console.inc @@ -0,0 +1,340 @@ + +jmp console0 + +#define __STR(X) #X +#define STR(X) __STR(X) + + +#undef STR + /* uses: ax, dx */ +#if defined(SERIAL_CONSOLE) +#define __CONSOLE_INLINE_TX_AL TTYS0_TX_AL +#else +#define __CONSOLE_INLINE_TX_AL +#endif + + /* uses: esp, ax, dx */ +#define __CONSOLE_TX_CHAR(byte) \ + mov byte, %al ; \ + CALLSP(console_tx_al) + + /* uses: ax, dx */ +#define __CONSOLE_INLINE_TX_CHAR(byte) \ + mov byte, %al ; \ + __CONSOLE_INLINE_TX_AL + + /* uses: esp, ax, edx */ +#define __CONSOLE_TX_HEX8(byte) \ + mov byte, %al ; \ + CALLSP(console_tx_hex8) + + /* uses: byte, ax, dx */ +#define __CONSOLE_INLINE_TX_HEX8(byte) \ + movb byte, %dl ; \ + shll $16, %edx ; \ + shr $4, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + shrl $16, %edx ; \ + movb %dl, %al ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL + + /* uses: esp, eax, ebx, dx */ +#define __CONSOLE_TX_HEX32(lword) \ + mov lword, %eax ; \ + CALLSP(console_tx_hex32) + + /* uses: eax, lword, dx */ +#define __CONSOLE_INLINE_TX_HEX32(lword) \ + mov lword, %eax ; \ + shr $28, %eax ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $24, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $20, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $16, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $12, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $8, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + shr $4, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL ; \ + ; \ + mov lword, %eax ; \ + and $0x0f, %al ; \ + add $'0', %al ; \ + cmp $'9', %al ; \ + jle 9f ; \ + add $39, %al ; \ +9: ; \ + __CONSOLE_INLINE_TX_AL + + + /* uses: esp, ebx, ax, dx */ +#define __CONSOLE_TX_STRING(string) \ + mov string, %ebx ; \ + CALLSP(console_tx_string) + + /* uses: ebx, ax, dx */ +#define __CONSOLE_INLINE_TX_STRING(string) \ + movl string, %ebx ; \ +10: movb (%ebx), %al ; \ + incl %ebx ; \ + testb %al, %al ; \ + jz 11f ; \ + __CONSOLE_INLINE_TX_AL ; \ + jmp 10b ; \ +11: + + +#define CONSOLE_EMERG_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_EMERG_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_EMERG_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_EMERG_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_EMERG_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_EMERG_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_EMERG_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_EMERG_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_ALERT_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_ALERT_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_ALERT_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_ALERT_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_ALERT_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_ALERT_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_ALERT_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_ALERT_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_CRIT_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_CRIT_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_CRIT_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_CRIT_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_CRIT_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_CRIT_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_CRIT_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_CRIT_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_ERR_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_ERR_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_ERR_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_ERR_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_ERR_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_ERR_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_ERR_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_ERR_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_WARNING_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_WARNING_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_WARNING_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_WARNING_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_WARNING_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_WARNING_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_WARNING_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_WARNING_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_NOTICE_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_NOTICE_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_NOTICE_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_NOTICE_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_NOTICE_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_NOTICE_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_NOTICE_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_NOTICE_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_INFO_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_INFO_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_INFO_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_INFO_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_INFO_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_INFO_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_INFO_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_INFO_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_DEBUG_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_DEBUG_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_DEBUG_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_DEBUG_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_DEBUG_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_DEBUG_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_DEBUG_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_DEBUG_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + +#define CONSOLE_SPEW_TX_CHAR(byte) __CONSOLE_TX_CHAR(byte) +#define CONSOLE_SPEW_INLINE_TX_CHAR(byte) __CONSOLE_INLINE_TX_CHAR(byte) +#define CONSOLE_SPEW_TX_HEX8(byte) __CONSOLE_TX_HEX8(byte) +#define CONSOLE_SPEW_INLINE_TX_HEX8(byte) __CONSOLE_INLINE_TX_HEX8(byte) +#define CONSOLE_SPEW_TX_HEX32(lword) __CONSOLE_TX_HEX32(lword) +#define CONSOLE_SPEW_INLINE_TX_HEX32(lword) __CONSOLE_INLINE_TX_HEX32(lword) +#define CONSOLE_SPEW_TX_STRING(string) __CONSOLE_TX_STRING(string) +#define CONSOLE_SPEW_INLINE_TX_STRING(string) __CONSOLE_INLINE_TX_STRING(string) + + /* uses: esp, ax, dx */ +console_tx_al: + __CONSOLE_INLINE_TX_AL + RETSP + + /* uses: esp, ax, edx */ +console_tx_hex8: + __CONSOLE_INLINE_TX_HEX8(%al) + RETSP + + + /* uses: esp, ebx, eax, dx */ +console_tx_hex32: + mov %eax, %ebx + shr $28, %eax + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $24, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $20, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $16, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $12, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $8, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + shr $4, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + + mov %ebx, %eax + and $0x0f, %al + add $'0', %al + cmp $'9', %al + jle 9f + add $39, %al +9: + __CONSOLE_INLINE_TX_AL + RETSP + + /* Uses esp, ebx, ax, dx */ + +console_tx_string: + mov (%ebx), %al + inc %ebx + cmp $0, %al + jne 9f + RETSP +9: + __CONSOLE_INLINE_TX_AL + jmp console_tx_string + +console0: diff --git a/src/arch/x86/llshell/llshell.inc b/src/arch/x86/llshell/llshell.inc new file mode 100644 index 0000000000..a66ac150b5 --- /dev/null +++ b/src/arch/x86/llshell/llshell.inc @@ -0,0 +1,901 @@ + +#define RET_LABEL(label) \ + jmp label##_done + +#define CALL_LABEL(label) \ + jmp label ;\ +label##_done: + +#define CALLSP(func) \ + lea 0f, %esp ; \ + jmp func ; \ +0: + +#define RETSP \ + jmp *%esp + + +#include "console.inc" +#include "pci.inc" +#include "ramtest.inc" + +jmp llshell_out + +// (c) 2004 Bryan Chafy, This program is released under the GPL + +// LLShell, A low level interactive debug shell +// Designed to be an interactive shell that operates with zero +// system resources. For example at initial boot. + +// to use, jump to label "low_level_shell" +// set %esp to the return address for exiting + + +#define UART_BASEADDR $0x3f8 +#define resultreg %esi +#define subroutinereg %edi +#define freqtime $2193 // 1.93 * freq +#define timertime $6000 +.equ sys_IOPL, 110 + +// .data +// .text + +welcome: + .string "\r\n! Low Level Shell (LLShell) (c)2004 Bryan Chafy \r\n\r\n" +prompt: + .string "\r\n!> " +badcmd: + .string "bad command\r\n" +sorry: + .string "sorry, not yet implemented\r\n" +cmds: + .string "\r\nList of commands:\r\n \ +\r\nbeep -- pc speaker beep \ +\r\nrst (or RST) -- reset \ +\r\nout(b,w,l) <val> <port> -- raw out val at port \ +\r\nin(b,w,l) <port> -- show raw port value \ +\r\njmp <address> -- jmp to address (llshell addr is in eax) \ +\r\ncall <address> -- funcion call (assumes a working stack) \ +\r\ncli -- clear interrupts \ +\r\nsti -- enable interrupts \ +\r\npush <value> -- push value onto stack \ +\r\npop -- pop from stack and display \ +\r\nwm(b,w,l) <addr> <val> -- write mem \ +\r\ndm <addr> <lines> -- dump mem \ +\r\nmcp <src> <dst> <size> -- mem copy \ +\r\nmpat <pat> <dst> <size> -- mem pattern \ +\r\nmemt <begin> <end> -- memory test \ +\r\npcir(b,w,l) <loc> -- pci read config \ +\r\npciw(b,w,l) <loc> <val> -- pci write config \ +\r\ndl <addr> <size> -- memory download (display xor cheksum at completion) \ +\r\ncram <addr> <size> -- enable cache to be ram (experimental) \ +\r\nbaud <val> -- change baudrate (not yet implemented) \ +\r\nexit -- exit shell \ +\r\nAll values in hex (0x prefixing ok) \ +\r\n" + +cr: + .string "\r\n" +spaces: + .string " " + +// .globl _start +//ASSUME CS:@CODE, DS:@DATA + +// _start: + +// call ioperms + +low_level_shell: + +mov $preamble,subroutinereg +jmp beep +preamble: +mov $welcome,resultreg +mov $readcommand,subroutinereg +jmp displaystring + +readcommand: +mov $prompt,resultreg +mov $rcmd,subroutinereg +jmp displaystring + +rcmd: +mov $readcommand,subroutinereg +movl $0x0, resultreg + +readchar: +mov UART_BASEADDR+5,%dx +in %dx, %al +and $0x9f,%al +test $0x01,%al +jz readchar +mov UART_BASEADDR,%dx +in %dx,%al //char in al +xchg %al,%ah + +send_char: +mov UART_BASEADDR+5,%dx +us_wait: +in %dx,%al +test $0x20,%al +jz us_wait +mov UART_BASEADDR,%dx +xchg %al,%ah +out %al,%dx // output char + +cmp $0x0D,%al //CR +jnz eval_char +mov $0x0A,%ah +jmp send_char + +eval_char: +cmp $0x20,%al //space +jz cmdtable +cmp $0x0A,%al //CR +jz cmdtable +cmp $0x08,%al //BS +jnz additup +//subit: +shr $0x8,resultreg +jmp readchar +additup: +shl $0x8,resultreg +and $0xff,%eax +add %eax,resultreg +jmp readchar + +cmdtable: +mov resultreg,%eax +cmp $0,%eax +jz readcommand +cmp $0x74657374,%eax +jz dotest +cmp $0x68656c70,%eax +jz dohelp +cmp $0x0000003f,%eax +jz dohelp +cmp $0x6f757462,%eax +jz dooutb +cmp $0x6f757477,%eax +jz dooutw +cmp $0x6f75746c,%eax +jz dooutd +cmp $0x00696e62,%eax +jz doinb +cmp $0x00696e77,%eax +jz doinw +cmp $0x00696e6c,%eax +jz doind +cmp $0x63697262,%eax +jz pcirb +cmp $0x63697277,%eax +jz pcirw +cmp $0x6369726c,%eax +jz pcirl +cmp $0x63697762,%eax +jz pciwb +cmp $0x63697777,%eax +jz pciww +cmp $0x6369776c,%eax +jz pciwl +cmp $0x00776d62,%eax +jz wmemb +cmp $0x00776d77,%eax +jz wmemw +cmp $0x00776d6c,%eax +jz wmeml +cmp $0x0000646d,%eax +jz dodmem +cmp $0x6d656d74,%eax +jz memt // mem test +cmp $0x00727374,%eax +jz rst // reset +cmp $0x00525354,%eax +jz RST +cmp $0x62656570,%eax +jz beep +cmp $0x0000646c,%eax +jz dodl // download to mem <loc> <size> +cmp $0x006a6d70,%eax +jz jmpto // jump to location (eax holds return addr) +cmp $0x62617564,%eax +jz baud // change baudrate +cmp $0x00696e74,%eax +jz doint // trigger an interrupt +cmp $0x63616c6c,%eax +jz callto // call assumes memory +cmp $0x70757368,%eax +jz dopush // assumes mem +cmp $0x00706f70,%eax +jz dopop // assumes mem +cmp $0x6372616d,%eax +jz cram // cache ram trick <location> <size> +cmp $0x006d6370,%eax +jz mcp // mem copy <src> <dst> <size> +cmp $0x6d706174,%eax +jz dopattern +cmp $0x00636c69,%eax +jz docli +cmp $0x00737469,%eax +jz dosti +cmp $0x65786974,%eax +jz doexit +mov $badcmd,resultreg +mov $readcommand,subroutinereg +jmp displaystring + + +readnibbles: +movl $0x0, resultreg +readit: +mov UART_BASEADDR+5,%dx +in %dx, %al +and $0x9f,%al +test $0x1,%al +jz readit +mov UART_BASEADDR,%dx +in %dx,%al +xchg %al,%ah + +sendchar: +mov UART_BASEADDR+5,%dx +us_waitit: +in %dx,%al +test $0x20,%al +jz us_waitit +mov UART_BASEADDR,%dx +xchg %al,%ah +out %al,%dx // output char + +cmp $0x78,%al +jz readit +cmp $0x0D,%al //CR +jnz evalchar +mov $0x0A,%ah +jmp sendchar + +evalchar: +cmp $0x20,%al //space +jz gosub +cmp $0x0A,%al //CR +jz gosub +cmp $0x08,%al //BS +jnz processchar +//subit: +shr $0x04,resultreg +jmp readit +processchar: +cmp $0x3A,%al +jl subnum +cmp $0x47,%al +jl subcaps +//sublc: +sub $0x57,%al +jmp additupn +subcaps: +sub $0x37,%al +jmp additupn +subnum: +sub $0x30,%al +additupn: +shl $0x04,resultreg +and $0xf,%eax +add %eax,resultreg +jmp readit + +gosub: +jmp *subroutinereg + +//intersubcall +// eax,edx,esi,edi + +// ebx,ecx,ebp,esp(?) +// ds,es,fs,gs + +dotest: +mov $ramtest,resultreg +mov $test1a,subroutinereg +jmp displayhex +test1a: +mov $welcome,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +dodmem: + +movl $dmem1a, subroutinereg +jmp readnibbles +dmem1a: +mov resultreg,%ebx // address +movl $dmem1b, subroutinereg +jmp readnibbles +dmem1b: +mov resultreg,%ecx // length + +dmemloop: +mov %ebx,resultreg +mov $daddr1,subroutinereg +jmp displayhex +daddr1: +mov $spaces,resultreg +mov $startshowm,subroutinereg +jmp displaystring + +startshowm: +mov (%ebx),resultreg +mov $showm1,subroutinereg +jmp displayhexlinear +showm1: +add $0x04,%ebx +mov (%ebx),resultreg +mov $showm2,subroutinereg +jmp displayhexlinear +showm2: +add $0x04,%ebx +mov (%ebx),resultreg +mov $showm3,subroutinereg +jmp displayhexlinear +showm3: +add $0x04,%ebx +mov (%ebx),resultreg +mov $showa0,subroutinereg +jmp displayhexlinear + +showa0: +sub $0xC,%ebx +mov (%ebx),resultreg +mov $showa1,subroutinereg +jmp displayasciilinear +showa1: +add $0x04,%ebx +mov (%ebx),resultreg +mov $showa2,subroutinereg +jmp displayasciilinear +showa2: +add $0x04,%ebx +mov (%ebx),resultreg +mov $showa3,subroutinereg +jmp displayasciilinear +showa3: +add $0x04,%ebx +mov (%ebx),resultreg +mov $doneshow,subroutinereg +jmp displayasciilinear +doneshow: +mov $cr,resultreg +mov $doneshow1,subroutinereg +jmp displaystring +doneshow1: +dec %cx +cmp $0x0,%cx +jz exitdmem +add $0x04,%ebx +jmp dmemloop +exitdmem: +jmp readcommand + +dooutb: +// out val,port +movl $outb1a, subroutinereg +jmp readnibbles +outb1a: +mov resultreg,%ebx +movl $outb1b, subroutinereg +jmp readnibbles +outb1b: +mov resultreg,%edx +mov %ebx,%eax +out %al,%dx +jmp readcommand + +dooutw: +// out val,port +movl $outw1a, subroutinereg +jmp readnibbles +outw1a: +mov resultreg,%ebx +movl $outw1b, subroutinereg +jmp readnibbles +outw1b: +mov resultreg,%edx +mov %ebx,%eax +out %ax,%dx +jmp readcommand + +dooutd: +// out val,port +movl $outd1a, subroutinereg +jmp readnibbles +outd1a: +mov resultreg,%ebx +movl $outd1b, subroutinereg +jmp readnibbles +outd1b: +mov resultreg,%edx +mov %ebx,%eax +out %eax,%dx +jmp readcommand + +wmemb: +movl $wmemba, subroutinereg +jmp readnibbles +wmemba: +mov resultreg,%ebx +movl $wmembb, subroutinereg +jmp readnibbles +wmembb: +mov resultreg,%eax +mov %al,(%ebx) +jmp readcommand + +wmemw: +movl $wmemwa, subroutinereg +jmp readnibbles +wmemwa: +mov resultreg,%ebx +movl $wmemwb, subroutinereg +jmp readnibbles +wmemwb: +mov resultreg,%eax +mov %ax,(%ebx) +jmp readcommand + +wmeml: +movl $wmemla, subroutinereg +jmp readnibbles +wmemla: +mov resultreg,%ebx +movl $wmemlb, subroutinereg +jmp readnibbles +wmemlb: +mov resultreg,%eax +mov %eax,(%ebx) +jmp readcommand + +doinb: +// in port +movl $inb1a, subroutinereg +jmp readnibbles +inb1a: +mov resultreg,%edx +mov $0x0,%eax +in %dx,%al +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +doinw: +// in port +movl $inw1a, subroutinereg +jmp readnibbles +inw1a: +mov resultreg,%edx +mov $0x0,%eax +in %dx,%ax +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +doind: +// in port +movl $ind1a, subroutinereg +jmp readnibbles +ind1a: +mov resultreg,%edx +in %dx,%eax +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +jmpto: +movl $jmp1a, subroutinereg +jmp readnibbles +jmp1a: +mov $readcommand,%eax +jmp *resultreg + +callto: +movl $call1a, subroutinereg +jmp readnibbles +call1a: +mov $readcommand,%eax +call *resultreg +jmp readcommand + +dopush: +movl $push1a, subroutinereg +jmp readnibbles +push1a: +mov resultreg,%eax +push %eax +jmp readcommand + +doint: +movl $int1a, subroutinereg +jmp readnibbles +int1a: +mov resultreg,%eax +// need to lookup int table? +// int %eax +jmp readcommand + +doenter: +//setup stack frame + + +dopop: +movl $readcommand, subroutinereg +pop resultreg +jmp displayhex + +docli: +cli +jmp readcommand + +dosti: +sti +jmp readcommand + + +displaystring: +// resultreg= pointer to string terminated by \0 +dsloop: +movb (resultreg),%ah +cmp $0x0, %ah +jz displaystringexit +mov UART_BASEADDR+5,%dx +us_waits: +in %dx,%al +test $0x20,%al +jz us_waits +mov UART_BASEADDR,%dx +xchg %al,%ah +out %al,%dx // output char +inc resultreg +jmp dsloop +displaystringexit: +jmp *subroutinereg + +displayhexlinear: +mov resultreg,%eax +xchg %al,%ah +rol $0x10,%eax +xchg %al,%ah +mov %eax,resultreg +displayhex: +rol $0x10,%ecx +mov $0x8,%cx +dhloop: +cmp $0xf,%cl +je exitdisplayhex +rol $0x04,resultreg +movl resultreg,%eax +and $0xf,%al +cmp $0xa,%al +jl addnum +//addcaps +add $0x37,%al +jmp outcharhex +addnum: +add $0x30,%al +outcharhex: +xchg %al,%ah +mov UART_BASEADDR+5,%dx +us_waith: +in %dx,%al +test $0x20,%al +jz us_waith +mov UART_BASEADDR,%dx +xchg %al,%ah +out %al,%dx // output char +dec %cx +cmp $0x0,%cx +jne dhloop +mov $0x20,%al +mov $0x10,%cl +jmp outcharhex +exitdisplayhex: +rol $0x10,%ecx +jmp *subroutinereg + +displayasciilinear: +mov resultreg,%eax +xchg %al,%ah +rol $0x10,%eax +xchg %al,%ah +mov %eax,resultreg +displayascii: +rol $0x10,%ecx +mov $0x4,%cx +daloop: +rol $0x08,resultreg +movl resultreg,%eax +cmp $0x7e,%al +jg unprintable +cmp $0x20,%al +jl unprintable +jmp outcharascii +unprintable: +mov $0x2e,%al // dot +outcharascii: +xchg %al,%ah +mov UART_BASEADDR+5,%dx +us_waita: +in %dx,%al +test $0x20,%al +jz us_waita +mov UART_BASEADDR,%dx +xchg %al,%ah +out %al,%dx // output char +dec %cx +cmp $0x0,%cx +jne daloop +rol $0x10,%ecx +jmp *subroutinereg + +rst: +cli +movb $0x0fe,%al +out %al,$0x64 +hlt + +RST: +cli +lidt %cs:0x03fff +int $0x3 +hlt + + +beep: +mov timertime,%eax +rol $0x10,%eax +mov $0xb6,%al +out %al,$0x43 +mov freqtime,%ax +out %al,$0x42 +xchg %al,%ah +out %al,$0x42 + +in $0x61,%al +or $0x03,%al +out %al,$0x61 + +//timer here +timer: +in $0x42,%al +// xchg %al,%ah +in $0x42,%al +// xchg %al,%ah +cmp $0x0,%al +jnz timer +rol $0x10,%eax +dec %ax +cmp $0x0,%ax; +rol $0x10,%eax +jnz timer +// timer + +in $0x61,%al +and $0xfc,%al +out %al,$0x61 +jmp *subroutinereg + +dohelp: +mov $cmds,resultreg +mov $readcommand,subroutinereg +jmp displaystring + +memt: +movl $memt1, subroutinereg +jmp readnibbles +memt1: +mov resultreg,%ecx +movl $memt2, subroutinereg +jmp readnibbles +memt2: +mov resultreg,%ebx +xchg %ecx,%eax +mov $readcommand,%esp // internal to linux bios +jmp ramtest + +pcirb: +movl $pcirb1, subroutinereg +jmp readnibbles +pcirb1: +mov resultreg,%eax +PCI_READ_CONFIG_BYTE +and $0xff,%eax +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +pcirw: +movl $pcirw1, subroutinereg +jmp readnibbles +pcirw1: +mov resultreg,%eax +PCI_READ_CONFIG_WORD +and $0xffff,%eax +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + +pcirl: +movl $pcirl1, subroutinereg +jmp readnibbles +pcirl1: +mov resultreg,%eax +PCI_READ_CONFIG_DWORD +mov %eax,resultreg +mov $readcommand,subroutinereg +jmp displayhex + + + + +pciwb: +movl $pciwb1, subroutinereg +jmp readnibbles +pciwb1: +mov resultreg,%ebx +movl $pciwb2, subroutinereg +jmp readnibbles +pciwb2: +mov resultreg,%edx +mov %ebx,%eax +PCI_WRITE_CONFIG_BYTE +jmp readcommand + +pciww: +movl $pciww1, subroutinereg +jmp readnibbles +pciww1: +mov resultreg,%ebx +movl $pciww2, subroutinereg +jmp readnibbles +pciww2: +mov resultreg,%ecx +mov %ebx,%eax +PCI_WRITE_CONFIG_WORD +jmp readcommand + +pciwl: +movl $pciwl1, subroutinereg +jmp readnibbles +pciwl1: +mov resultreg,%ebx +movl $pciwl2, subroutinereg +jmp readnibbles +pciwl2: +mov resultreg,%ecx +mov %ebx,%eax +PCI_WRITE_CONFIG_DWORD +jmp readcommand + +cram: +//likely not working. Just testing for now +movl $cram1, subroutinereg +jmp readnibbles +cram1: +mov resultreg,%ebx +movl $cram1, subroutinereg +jmp readnibbles +cram2: +mov resultreg,%ecx +// enable it +mov %cr0,%eax +and $0x9fffffff,%eax // also try 0x0fff, 0x2ff(write back)... +mov %eax,%cr0 +//wbinvd ?? +cacheloop: +mov (%ebx),%eax +inc %ebx +loop cacheloop +// disable it +mov %cr0,%eax +or $0x60000000,%eax +mov %eax,%cr0 +//wbinvd ?? + +dodl: +movl $dl1, subroutinereg +jmp readnibbles +dl1: +mov resultreg,%ebx +movl $dl2, subroutinereg +jmp readnibbles +dl2: +mov resultreg,%ecx +mov resultreg,subroutinereg +mov %ebx,resultreg +dlloop: +mov UART_BASEADDR+5,%dx +in %dx, %al +and $0x9f,%al +test $0x01,%al +jz dlloop +mov UART_BASEADDR,%dx +in %dx,%al +mov %al,(%ebx) +inc %ebx +loop dlloop +csum: +mov subroutinereg,%ecx +shr $0x02,%ecx +mov resultreg,%ebx +mov $0x0,%eax +csumloop: +rol $0x03,%eax +mov (%ebx),%dl +xor %dl,%al +inc %ebx +loop csumloop +mov $readcommand,subroutinereg +mov %eax,resultreg +jmp displayhex + +baud: +mov $sorry,resultreg +mov $readcommand,subroutinereg +jmp displaystring + +mcp: +movl $mcp1, subroutinereg +jmp readnibbles +mcp1: +mov resultreg,%ebx +movl $mcp2, subroutinereg +jmp readnibbles +mcp2: +mov resultreg,%ecx +movl $mcp3, subroutinereg +jmp readnibbles +mcp3: +mov resultreg,%eax +xchg %ecx,%eax +mcploop: +mov (%ebx),%dl +mov %dl,(%eax) +inc %ebx +inc %eax +loop mcploop +jmp readcommand + +dopattern: +movl $pat1, subroutinereg +jmp readnibbles +pat1: +mov resultreg,%ebx +movl $pat2, subroutinereg +jmp readnibbles +pat2: +mov resultreg,%ecx +movl $pat3, subroutinereg +jmp readnibbles +pat3: +mov resultreg,%eax +xchg %ecx,%eax +patloop: +rol $0x08,%ebx +mov %bl,(%eax) +inc %eax +loop patloop +jmp readcommand + + +doexit: + // LB specific: +RETSP // if there's no stack yet, caller must set %esp manually +// RET_LABEL(low_level_shell) + + +//Linux OS Specific +ioperms: +movl $sys_IOPL, %eax # system-call ID-number +movl $3, %ebx # new value for IO0PL +int $0x80 # enter the kernel +ret + +llshell_out: diff --git a/src/arch/x86/llshell/pci.inc b/src/arch/x86/llshell/pci.inc new file mode 100644 index 0000000000..7cb741008e --- /dev/null +++ b/src/arch/x86/llshell/pci.inc @@ -0,0 +1,229 @@ + + /* + * Macro: PCI_WRITE_CONFIG_BYTE + * Arguments: %eax address to write to (includes bus, device, function, &offset) + * %dl byte to write + * + * Results: none + * + * Trashed: %eax, %edx + * Effects: writes a single byte to pci config space + * + * Notes: This routine is optimized for minimal register usage. + * And the tricks it does cannot scale beyond writing a single byte. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the data byte + * in the high half of edx. + * + * In %edx[3] it stores the byte to write. + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_WRITE_CONFIG_BYTE \ + shll $8, %edx ; \ + movb %al, %dl ; \ + andb $0x3, %dl ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + movb %dh, %al ; \ + movb $0, %dh ; \ + addl $0xcfc, %edx ; \ + outb %al, %dx + + + /* + * Macro: PCI_WRITE_CONFIG_WORD + * Arguments: %eax address to write to (includes bus, device, function, &offset) + * %ecx word to write + * + * Results: none + * + * Trashed: %eax, %edx + * Preserved: %ecx + * Effects: writes a single byte to pci config space + * + * Notes: This routine is optimized for minimal register usage. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the least significant + * bits of the address in the high half of edx. + * + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_WRITE_CONFIG_WORD \ + movb %al, %dl ; \ + andl $0x3, %edx ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + movl %ecx, %eax ; \ + addl $0xcfc, %edx ; \ + outw %ax, %dx + + + + /* + * Macro: PCI_WRITE_CONFIG_DWORD + * Arguments: %eax address to write to (includes bus, device, function, &offset) + * %ecx dword to write + * + * Results: none + * + * Trashed: %eax, %edx + * Preserved: %ecx + * Effects: writes a single byte to pci config space + * + * Notes: This routine is optimized for minimal register usage. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the least significant + * bits of the address in the high half of edx. + * + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_WRITE_CONFIG_DWORD \ + movb %al, %dl ; \ + andl $0x3, %edx ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + movl %ecx, %eax ; \ + addl $0xcfc, %edx ; \ + outl %eax, %dx + + + + + /* + * Macro: PCI_READ_CONFIG_BYTE + * Arguments: %eax address to read from (includes bus, device, function, &offset) + * + * Results: %al Byte read + * + * Trashed: %eax, %edx + * Effects: reads a single byte from pci config space + * + * Notes: This routine is optimized for minimal register usage. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the least significant + * bits of the address in the high half of edx. + * + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_READ_CONFIG_BYTE \ + movb %al, %dl ; \ + andl $0x3, %edx ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + addl $0xcfc, %edx ; \ + inb %dx, %al + + + + /* + * Macro: PCI_READ_CONFIG_WORD + * Arguments: %eax address to read from (includes bus, device, function, &offset) + * + * Results: %ax word read + * + * Trashed: %eax, %edx + * Effects: reads a 2 bytes from pci config space + * + * Notes: This routine is optimized for minimal register usage. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the least significant + * bits of the address in the high half of edx. + * + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_READ_CONFIG_WORD \ + movb %al, %dl ; \ + andl $0x3, %edx ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + addl $0xcfc, %edx ; \ + inw %dx, %ax + + + + /* + * Macro: PCI_READ_CONFIG_DWORD + * Arguments: %eax address to read from (includes bus, device, function, &offset) + * + * Results: %eax + * + * Trashed: %edx + * Effects: reads 4 bytes from pci config space + * + * Notes: This routine is optimized for minimal register usage. + * + * What it does is almost simple. + * It preserves %eax (baring special bits) until it is written + * out to the appropriate port. And hides the least significant + * bits of the address in the high half of edx. + * + * In %edx[2] it stores the lower three bits of the address. + */ + + +#define PCI_READ_CONFIG_DWORD \ + movb %al, %dl ; \ + andl $0x3, %edx ; \ + shll $16, %edx ; \ + \ + orl $0x80000000, %eax ; \ + andl $0xfffffffc, %eax ; \ + movw $0xcf8, %dx ; \ + outl %eax, %dx ; \ + \ + shrl $16, %edx ; \ + addl $0xcfc, %edx ; \ + inl %dx, %eax + + + diff --git a/src/arch/x86/llshell/ramtest.inc b/src/arch/x86/llshell/ramtest.inc new file mode 100644 index 0000000000..c02cf451ec --- /dev/null +++ b/src/arch/x86/llshell/ramtest.inc @@ -0,0 +1,125 @@ + /* + * This is much more of a "Is my SDRAM properly configured?" + * test than a "Is my SDRAM faulty?" test. Not all bits + * are tested. -Tyson + */ + + jmp rt_skip +#define RAMTEST 1 +#if RAMTEST + .section ".rom.data" + +rt_test: .string "Testing SDRAM : " +rt_fill: .string "SDRAM fill:\r\n" +rt_verify: .string "SDRAM verify:\r\n" +rt_toomany: .string "Too many errors.\r\n" +rt_done: .string "Done.\r\n" + .previous +#endif + +ramtest: +#if RAMTEST + mov %eax, %esi + mov %ebx, %edi + mov %esp, %ebp + + CONSOLE_INFO_TX_STRING($rt_test) + CONSOLE_INFO_TX_HEX32(%esi) + CONSOLE_INFO_TX_CHAR($'-') + CONSOLE_INFO_TX_HEX32(%edi) + CONSOLE_INFO_TX_CHAR($'\r') + CONSOLE_INFO_TX_CHAR($'\n') + + /* ============== Fill ram block ==== */ + + CONSOLE_INFO_TX_STRING($rt_fill) + + mov %esi, %ebx +1: + cmp $0, %bx + jne 2f + + /* Display address being filled */ + /* CONSOLE_INFO_TX_HEX32(arg) will overwrite %ebx with arg */ + + CONSOLE_INFO_TX_HEX32(%ebx) + CONSOLE_INFO_TX_CHAR($'\r') +2: +#if i786 + /* Use a non temporal store to go faster and + * to bypass the cache. + */ + movnti %ebx, (%ebx) +#else + mov %ebx, (%ebx) +#endif + add $4, %ebx + cmp %edi, %ebx + jl 1b + + /* Display final address */ + + CONSOLE_INFO_TX_HEX32(%edi) + CONSOLE_INFO_TX_CHAR($'\r') + CONSOLE_INFO_TX_CHAR($'\n') + + /* ========= Verify ram block ========== */ + + CONSOLE_INFO_TX_STRING($rt_verify) + mov %esi, %ebx + +1: + cmp $0, %bx + jne 2f + + /* Display address being tested */ + + CONSOLE_INFO_TX_HEX32(%ebx) + CONSOLE_INFO_TX_CHAR($'\r') +2: + cmp %ebx, (%ebx) + jne 4f +3: + add $4, %ebx + cmp %edi, %ebx + jl 1b + + /* Display final address */ + CONSOLE_INFO_TX_HEX32(%edi) + CONSOLE_INFO_TX_CHAR($'\r') + CONSOLE_INFO_TX_CHAR($'\n') + jmp 6f + +4: + /* Display address with error */ + + CONSOLE_INFO_TX_HEX32(%ebx) + CONSOLE_INFO_TX_CHAR($':') + + /* Display data in address with error */ + + /* CONSOLE_INFO_TX_HEX32(arg) will overwrite %ebx with arg */ + + mov %ebx, %esi + mov 0(%ebx), %eax + CONSOLE_INFO_TX_HEX32(%eax) + mov %esi, %ebx + + CONSOLE_INFO_TX_CHAR($'\r') + CONSOLE_INFO_TX_CHAR($'\n') + sub $1, %ecx + jz 5f + jmp 3b +5: + CONSOLE_INFO_TX_STRING($rt_toomany) + post_code(0xf1) + jmp .Lhlt + +6: + CONSOLE_INFO_TX_STRING($rt_done) + mov %ebp, %esp + +#endif + RETSP + +rt_skip: diff --git a/src/arch/x86/llshell/readme.coreboot b/src/arch/x86/llshell/readme.coreboot new file mode 100644 index 0000000000..ae7dcbecd0 --- /dev/null +++ b/src/arch/x86/llshell/readme.coreboot @@ -0,0 +1,25 @@ + +1) Include llshell.inc in your northbridge Config file +2) In raminit.inc (or whatever), make a jmp out to low_level_shell, setting + a return label in %esp. +For example: +ram_set_registers: + + mov $llshell_ret1,%esp + jmp low_level_shell +llshell_ret1: + + /* Disable and invalidate the cache */ + invd + mov %cr0, %eax + .... +3) Optionally, comment out two lines in ramtest.inc: +5: + CONSOLE_INFO_TX_STRING($rt_toomany) + // post_code(0xf1) + // jmp .Lhlt +otherwise, a ramtest failure will hang + +4) build and flash as normal +If it worked, the speaker will beep, and you'll get a shell. +Type help or ? at the prompt for a list of commands. |