|
|
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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.