aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86/llshell
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/x86/llshell')
-rw-r--r--src/arch/x86/llshell/console.inc340
-rw-r--r--src/arch/x86/llshell/llshell.inc901
-rw-r--r--src/arch/x86/llshell/pci.inc229
-rw-r--r--src/arch/x86/llshell/ramtest.inc125
-rw-r--r--src/arch/x86/llshell/readme.coreboot25
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.