summaryrefslogtreecommitdiffstats
path: root/src/arch/i386/core/realmode.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/i386/core/realmode.c')
-rw-r--r--src/arch/i386/core/realmode.c150
1 files changed, 21 insertions, 129 deletions
diff --git a/src/arch/i386/core/realmode.c b/src/arch/i386/core/realmode.c
index ef4ede86..32252bd3 100644
--- a/src/arch/i386/core/realmode.c
+++ b/src/arch/i386/core/realmode.c
@@ -3,146 +3,38 @@
* Initial version by Michael Brown <mbrown@fensystems.co.uk>, January 2004.
*/
-#include "etherboot.h"
#include "realmode.h"
-#include "segoff.h"
-#define RM_STACK_SIZE ( 0x1000 )
-
-/* gcc won't let us use extended asm outside a function (compiler
- * bug), ao we have to put these asm statements inside a dummy
- * function.
- */
-static void work_around_gcc_bug ( void ) __attribute__ ((used));
-static void work_around_gcc_bug ( void ) {
- /* Export _real_mode_stack_size as absolute linker symbol */
- __asm__ ( ".globl _real_mode_stack_size" );
- __asm__ ( ".equ _real_mode_stack_size, %c0" : : "i" (RM_STACK_SIZE) );
-}
-
-/* While Etherboot remains in base memory the real-mode stack is
- * placed in the Etherboot main stack. The first allocation or
- * deallocation of base memory will cause a 'proper' real-mode stack
- * to be allocated. This will happen before Etherboot is relocated to
- * high memory.
- */
-uint32_t real_mode_stack = 0;
-size_t real_mode_stack_size = RM_STACK_SIZE;
-int lock_real_mode_stack = 0; /* Set to make stack immobile */
-
-/* Make a call to a real-mode code block.
- */
-
-/* These is the structure that exists on the stack as the paramters
- * passed in to _real_call. We pass a pointer to this struct to
- * prepare_real_call(), to save stack space.
+/*
+ * Copy data to/from base memory.
+ *
*/
-typedef struct {
- void *fragment;
- int fragment_len;
- void *in_stack;
- int in_stack_len;
- void *out_stack;
- int out_stack_len;
-} real_call_params_t;
-uint32_t prepare_real_call ( real_call_params_t *p,
- int local_stack_len, char *local_stack ) {
- char *stack_base;
- char *stack_end;
- char *stack;
- char *s;
- prot_to_real_params_t *p2r_params;
- real_to_prot_params_t *r2p_params;
+#ifdef KEEP_IT_REAL
- /* Work out where we're putting the stack */
- if ( virt_to_phys(local_stack) < 0xa0000 ) {
- /* Current stack is in base memory. We can therefore
- * use it directly, with a constraint on the size that
- * we don't know; assume that we can use up to
- * real_mode_stack_size. (Not a valid assumption, but
- * it will do).
- */
- stack_end = local_stack + local_stack_len;
- stack_base = stack_end - real_mode_stack_size;
- } else {
- if (!real_mode_stack) {
- allot_real_mode_stack();
- }
- /* Use the allocated real-mode stack in base memory.
- * This has fixed start and end points.
- */
- stack_base = phys_to_virt(real_mode_stack);
- stack_end = stack_base + real_mode_stack_size;
- }
- s = stack = stack_end - local_stack_len;
+void memcpy_to_real ( segoff_t dest, void *src, size_t n ) {
- /* Compile input stack and trampoline code to stack */
- if ( p->in_stack_len ) {
- memcpy ( s, p->in_stack, p->in_stack_len );
- s += p->in_stack_len;
- }
- memcpy ( s, _prot_to_real_prefix, prot_to_real_prefix_size );
- s += prot_to_real_prefix_size;
- p2r_params = (prot_to_real_params_t*) ( s - sizeof(*p2r_params) );
- memcpy ( s, p->fragment, p->fragment_len );
- s += p->fragment_len;
- memcpy ( s, _real_to_prot_suffix, real_to_prot_suffix_size );
- s += real_to_prot_suffix_size;
- r2p_params = (real_to_prot_params_t*) ( s - sizeof(*r2p_params) );
+}
- /* Set parameters within compiled stack */
- p2r_params->ss = p2r_params->cs = SEGMENT ( stack_base );
- p2r_params->esp = virt_to_phys ( stack );
- p2r_params->r2p_params = virt_to_phys ( r2p_params );
- r2p_params->out_stack = ( p->out_stack == NULL ) ?
- 0 : virt_to_phys ( p->out_stack );
- r2p_params->out_stack_len = p->out_stack_len;
+void memcpy_from_real ( void *dest, segoff_t src, size_t n ) {
- return virt_to_phys ( stack + p->in_stack_len );
}
+#endif /* KEEP_IT_REAL */
-/* Parameters are not genuinely unused; they are passed to
- * prepare_real_call() as part of a real_call_params_t struct.
- */
-uint16_t _real_call ( void *fragment, int fragment_len,
- void *in_stack __unused, int in_stack_len,
- void *out_stack __unused, int out_stack_len __unused ) {
- uint16_t retval;
- /* This code is basically equivalent to
- *
- * uint32_t trampoline;
- * char local_stack[ in_stack_len + prot_to_real_prefix_size +
- * fragment_len + real_to_prot_suffix_size ];
- * trampoline = prepare_real_call ( &fragment, local_stack );
- * __asm__ ( "call _virt_to_phys\n\t"
- * "call %%eax\n\t"
- * "call _phys_to_virt\n\t"
- * : "=a" (retval) : "0" (trampoline) );
- *
- * but implemented in assembly to avoid problems with not
- * being certain exactly how gcc handles %esp.
- */
+#define RM_STACK_SIZE ( 0x1000 )
- __asm__ ( "pushl %%ebp\n\t"
- "movl %%esp, %%ebp\n\t" /* %esp preserved via %ebp */
- "subl %%ecx, %%esp\n\t" /* space for inline RM stack */
- "pushl %%esp\n\t" /* set up RM stack */
- "pushl %%ecx\n\t"
- "pushl %%eax\n\t"
- "call prepare_real_call\n\t" /* %eax = trampoline addr */
- "addl $12, %%esp\n\t"
- "call _virt_to_phys\n\t" /* switch to phys addr */
- "call *%%eax\n\t" /* call to trampoline */
- "call _phys_to_virt\n\t" /* switch to virt addr */
- "movl %%ebp, %%esp\n\t" /* restore %esp & %ebp */
- "popl %%ebp\n\t"
- : "=a" ( retval )
- : "0" ( &fragment )
- , "c" ( ( ( in_stack_len + prot_to_real_prefix_size +
- fragment_len + real_to_prot_suffix_size )
- + 0x3 ) & ~0x3 ) );
- return retval;
+/* gcc won't let us use extended asm outside a function (compiler
+ * bug), ao we have to put these asm statements inside a dummy
+ * function.
+ */
+static void work_around_gcc_bug ( void ) __attribute__ ((used));
+static void work_around_gcc_bug ( void ) {
+ /* Export _real_mode_stack_size as absolute linker symbol */
+ __asm__ ( ".globl real_mode_stack_size" );
+ __asm__ ( ".equ real_mode_stack_size, %c0" : : "i" (RM_STACK_SIZE) );
}
+
+char *real_mode_stack;
+int lock_real_mode_stack;