Annotation of qemu/roms/ipxe/src/arch/i386/transitions/libkir.S, revision 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.