Annotation of qemu/roms/ipxe/src/arch/i386/transitions/libkir.S, revision 1.1.1.1

1.1       root        1: /*
                      2:  * libkir: a transition library for -DKEEP_IT_REAL
                      3:  *
                      4:  * Michael Brown <[email protected]>
                      5:  *
                      6:  */
                      7: 
                      8: FILE_LICENCE ( GPL2_OR_LATER )
                      9: 
                     10: /****************************************************************************
                     11:  * This file defines libkir: an interface between external and
                     12:  * internal environments when -DKEEP_IT_REAL is used, so that both
                     13:  * internal and external environments are in real mode.  It deals with
                     14:  * switching data segments and the stack.  It provides the following
                     15:  * functions:
                     16:  *
                     17:  * ext_to_kir &                switch between external and internal (kir)
                     18:  * kir_to_ext          environments, preserving all non-segment
                     19:  *                     registers
                     20:  *
                     21:  * kir_call            issue a call to an internal routine from external
                     22:  *                     code
                     23:  *
                     24:  * libkir is written to avoid assuming that segments are anything
                     25:  * other than opaque data types, and also avoids assuming that the
                     26:  * stack pointer is 16-bit.  This should enable it to run just as well
                     27:  * in 16:16 or 16:32 protected mode as in real mode.
                     28:  ****************************************************************************
                     29:  */
                     30: 
                     31: /* Breakpoint for when debugging under bochs */
                     32: #define BOCHSBP xchgw %bx, %bx
                     33: 
                     34:        .text
                     35:        .arch i386
                     36:        .section ".text16", "awx", @progbits
                     37:        .code16
                     38:        
                     39: /****************************************************************************
                     40:  * init_libkir (real-mode or 16:xx protected-mode far call)
                     41:  *
                     42:  * Initialise libkir ready for transitions to the kir environment
                     43:  *
                     44:  * Parameters:
                     45:  *   %cs : .text16 segment
                     46:  *   %ds : .data16 segment
                     47:  ****************************************************************************
                     48:  */
                     49:        .globl  init_libkir
                     50: init_libkir:
                     51:        /* Record segment registers */
                     52:        pushw   %ds
                     53:        popw    %cs:kir_ds
                     54:        lret
                     55:        
                     56: /****************************************************************************
                     57:  * ext_to_kir (real-mode or 16:xx protected-mode near call)
                     58:  *
                     59:  * Switch from external stack and segment registers to internal stack
                     60:  * and segment registers.  %ss:sp is restored from the saved kir_ds
                     61:  * and kir_sp.  %ds, %es, %fs and %gs are all restored from the saved
                     62:  * kir_ds.  All other registers are preserved.
                     63:  *
                     64:  * %cs:0000 must point to the start of the runtime image code segment
                     65:  * on entry.
                     66:  *
                     67:  * Parameters: none
                     68:  ****************************************************************************
                     69:  */
                     70: 
                     71:        .globl  ext_to_kir
                     72: ext_to_kir:
                     73:        /* Record external segment registers */
                     74:        movw    %ds, %cs:ext_ds
                     75:        pushw   %cs
                     76:        popw    %ds     /* Set %ds = %cs for easier access to variables */
                     77:        movw    %es, %ds:ext_es
                     78:        movw    %fs, %ds:ext_fs
                     79:        movw    %gs, %ds:ext_fs
                     80: 
                     81:        /* Preserve registers */
                     82:        movw    %ax, %ds:save_ax
                     83: 
                     84:        /* Extract near return address from stack */
                     85:        popw    %ds:save_retaddr
                     86: 
                     87:        /* Record external %ss:esp */
                     88:        movw    %ss, %ds:ext_ss
                     89:        movl    %esp, %ds:ext_esp
                     90: 
                     91:        /* Load internal segment registers and stack pointer */
                     92:        movw    %ds:kir_ds, %ax
                     93:        movw    %ax, %ss
                     94:        movzwl  %ds:kir_sp, %esp
                     95:        movw    %ax, %ds
                     96:        movw    %ax, %es
                     97:        movw    %ax, %fs
                     98:        movw    %ax, %gs
                     99: 1:
                    100: 
                    101:        /* Place return address on new stack */
                    102:        pushw   %cs:save_retaddr
                    103:        
                    104:        /* Restore registers and return */
                    105:        movw    %cs:save_ax, %ax
                    106:        ret
                    107: 
                    108: /****************************************************************************
                    109:  * kir_to_ext (real-mode or 16:xx protected-mode near call)
                    110:  *
                    111:  * Switch from internal stack and segment registers to external stack
                    112:  * and segment registers.  %ss:%esp is restored from the saved ext_ss
                    113:  * and ext_esp.  Other segment registers are restored from the
                    114:  * corresponding locations.  All other registers are preserved.
                    115:  *
                    116:  * Note that it is actually %ss that is recorded as kir_ds, on the
                    117:  * assumption that %ss == %ds when kir_to_ext is called.
                    118:  *
                    119:  * Parameters: none
                    120:  ****************************************************************************
                    121:  */
                    122: 
                    123:        .globl  kir_to_ext
                    124: kir_to_ext:
                    125:        /* Record near return address */
                    126:        pushw   %cs
                    127:        popw    %ds     /* Set %ds = %cs for easier access to variables */
                    128:        popw    %ds:save_retaddr
                    129:        
                    130:        /* Record internal segment registers and %sp */
                    131:        movw    %ss, %ds:kir_ds
                    132:        movw    %sp, %ds:kir_sp
                    133: 
                    134:        /* Load external segment registers and stack pointer */
                    135:        movw    %ds:ext_ss, %ss
                    136:        movl    %ds:ext_esp, %esp
                    137:        movw    %ds:ext_gs, %gs
                    138:        movw    %ds:ext_fs, %fs
                    139:        movw    %ds:ext_es, %es
                    140:        movw    %ds:ext_ds, %ds
                    141: 
                    142:        /* Return */
                    143:        pushw   %cs:save_retaddr
                    144:        ret
                    145:        
                    146: /****************************************************************************
                    147:  * kir_call (real-mode or 16:xx protected-mode far call)
                    148:  *
                    149:  * Call a specific C function in the internal code.  The prototype of
                    150:  * the C function must be
                    151:  *   void function ( struct i386_all_resg *ix86 ); 
                    152:  * ix86 will point to a struct containing the real-mode registers
                    153:  * at entry to kir_call.
                    154:  *
                    155:  * All registers will be preserved across kir_call(), unless the C
                    156:  * function explicitly overwrites values in ix86.  Interrupt status
                    157:  * will also be preserved.
                    158:  *
                    159:  * Parameters:
                    160:  *   function : (32-bit) virtual address of C function to call
                    161:  *
                    162:  * Example usage:
                    163:  *     pushl   $pxe_api_call
                    164:  *     lcall   $UNDI_CS, $kir_call
                    165:  *     addw    $4, %sp
                    166:  * to call in to the C function
                    167:  *      void pxe_api_call ( struct i386_all_regs *ix86 );
                    168:  ****************************************************************************
                    169:  */
                    170: 
                    171:        .globl  kir_call
                    172: kir_call:
                    173:        /* Preserve flags.  Must do this before any operation that may
                    174:         * affect flags.
                    175:         */
                    176:        pushfl
                    177:        popl    %cs:save_flags
                    178: 
                    179:        /* Disable interrupts.  We do funny things with the stack, and
                    180:         * we're not re-entrant.
                    181:         */
                    182:        cli
                    183:                
                    184:        /* Extract address of internal routine from stack.  We must do
                    185:         * this without using (%bp), because we may be called with
                    186:         * either a 16-bit or a 32-bit stack segment.
                    187:         */
                    188:        popl    %cs:save_retaddr        /* Scratch location */
                    189:        popl    %cs:save_function
                    190:        subl    $8, %esp                /* Restore %esp */
                    191:        
                    192:        /* Switch to internal stack.  Note that the external stack is
                    193:         * inaccessible once we're running internally (since we have
                    194:         * no concept of 48-bit far pointers)
                    195:         */
                    196:        call    ext_to_kir
                    197:        
                    198:        /* Store external registers on internal stack */
                    199:        pushl   %cs:save_flags
                    200:        pushal
                    201:        pushl   %cs:ext_fs_and_gs
                    202:        pushl   %cs:ext_ds_and_es
                    203:        pushl   %cs:ext_cs_and_ss
                    204: 
                    205:        /* Push &ix86 on stack and call function */
                    206:        sti
                    207:        pushl   %esp
                    208:        data32 call *%cs:save_function
                    209:        popl    %eax /* discard */
                    210:        
                    211:        /* Restore external registers from internal stack */
                    212:        popl    %cs:ext_cs_and_ss
                    213:        popl    %cs:ext_ds_and_es
                    214:        popl    %cs:ext_fs_and_gs
                    215:        popal
                    216:        popl    %cs:save_flags
                    217: 
                    218:        /* Switch to external stack */
                    219:        call    kir_to_ext
                    220: 
                    221:        /* Restore flags */
                    222:        pushl   %cs:save_flags
                    223:        popfl
                    224: 
                    225:        /* Return */
                    226:        lret
                    227: 
                    228: /****************************************************************************
                    229:  * Stored internal and external stack and segment registers
                    230:  ****************************************************************************
                    231:  */
                    232:        
                    233: ext_cs_and_ss: 
                    234: ext_cs:                .word 0
                    235: ext_ss:                .word 0
                    236: ext_ds_and_es: 
                    237: ext_ds:                .word 0
                    238: ext_es:                .word 0
                    239: ext_fs_and_gs: 
                    240: ext_fs:                .word 0
                    241: ext_gs:                .word 0
                    242: ext_esp:       .long 0
                    243: 
                    244:                .globl kir_ds
                    245: kir_ds:                .word 0
                    246:                .globl kir_sp
                    247: kir_sp:                .word _estack
                    248: 
                    249: /****************************************************************************
                    250:  * Temporary variables
                    251:  ****************************************************************************
                    252:  */
                    253: save_ax:       .word 0
                    254: save_retaddr:  .long 0
                    255: save_flags:    .long 0
                    256: save_function: .long 0

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.