/**************************************************************************** * This file provides the setup() and setup16() functions. The * purpose of these functions is to set up the internal environment so * that C code can execute. This includes setting up the internal * stack and (where applicable) setting up a GDT for virtual * addressing. * * These functions are designed to be called by the prefix. * * The same basic assembly code is used to compile both setup() * and setup16(). **************************************************************************** */ .text .arch i386 #ifdef CODE16 /**************************************************************************** * setup16 (real-mode far call) * * This function can be called by a 16-bit prefix in order to set up * the internal (either 16-bit or 32-bit) environment. * * Parameters: none * * %cs:0000, %ds:0000 and %es:0000 must point to the start of the * (decompressed) runtime image. * * If KEEP_IT_REAL is defined, then %ds:0000 may instead point to the * start of the (decompressed) data segment portion of the runtime * image. If %ds==%cs, then it will be assumed that the data segment * follows immediately after the code segment. **************************************************************************** */ #ifdef KEEP_IT_REAL #define ENTER_FROM_EXTERNAL call ext_to_kir #define RETURN_TO_EXTERNAL call kir_to_ext #define ENTRY_POINT kir_call #else /* KEEP_IT_REAL */ #define ENTER_FROM_EXTERNAL \ pushw %cs ; \ call real_to_prot ; \ .code32 #define RETURN_TO_EXTERNAL \ call prot_to_real ; \ .code16 #define ENTRY_POINT _prot_call /* _prot_call = OFFSET ( prot_call ) in librm */ #endif /* KEEP_IT_REAL */ #define ENTRY_POINT_REGISTER di .section ".text16" .code16 .globl setup16 setup16: #else /* CODE16 */ /**************************************************************************** * setup (32-bit protected-mode near call) * * This function can be called by a 32-bit prefix in order to set up * the internal 32-bit environment. * * Parameters: none **************************************************************************** */ #define ENTER_FROM_EXTERNAL call ext_to_int #define RETURN_TO_EXTERNAL call int_to_ext #define ENTRY_POINT int_call #define ENTRY_POINT_REGISTER edi .section ".text" .code32 .globl setup setup: #endif /* CODE16 */ /* Preserve flags (including interrupt status) */ pushfl /* Switch to (uninitialised) internal environment. This will * preserve the external environment for when we call * RETURN_TO_EXTERNAL. */ ENTER_FROM_EXTERNAL /* NOTE: We may have only four bytes of stack at this point */ #if defined(CODE16) && defined(KEEP_IT_REAL) /* If %ds == %cs, then the data segment is located immediately * after the code segment. */ pushw %ax pushw %bx movw %cs, %ax movw %ds, %bx cmpw %ax, %bx jne 1f addw $_text_load_size_pgh, %ax movw %ax, %ds 1: popw %bx popw %ax /* Switch to internal stack */ pushw %ds popw %ss movl $_estack, %esp #else /* CODE16 && KEEP_IT_REAL */ /* Work out where we're running */ call 1f 1: popl %ebp /* Switch to internal pmode stack */ leal (_estack-1b)(%ebp), %esp /* Set up GDT for virtual addressing */ call run_here #endif /* CODE16 && KEEP_IT_REAL */ /* Switch back to external environment. This will preserve * the internal environment ready for the next call. */ RETURN_TO_EXTERNAL /* Pass pointer to entry-point function back to prefix. %es * may, by now, have been destroyed, so we re-initialise it * from %cs. */ pushw %cs popw %es mov $ENTRY_POINT, %ENTRY_POINT_REGISTER /* Restore flags (including interrupt status) */ popfl lret /**************************************************************************** * Internal stack **************************************************************************** */ .section ".stack" .align 8 _stack: .space 4096 _estack: