summaryrefslogtreecommitdiffstats
path: root/qemu/roms/openbios/arch/x86/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/openbios/arch/x86/entry.S')
-rw-r--r--qemu/roms/openbios/arch/x86/entry.S315
1 files changed, 315 insertions, 0 deletions
diff --git a/qemu/roms/openbios/arch/x86/entry.S b/qemu/roms/openbios/arch/x86/entry.S
new file mode 100644
index 000000000..8f1e42eed
--- /dev/null
+++ b/qemu/roms/openbios/arch/x86/entry.S
@@ -0,0 +1,315 @@
+ .globl entry, __switch_context, __exit_context, halt, init_exceptions
+
+ .text
+ .align 4
+
+/*
+ * Entry point
+ * We start execution from here.
+ * It is assumed that CPU is in 32-bit protected mode and
+ * all segments are 4GB and base zero (flat model).
+ */
+entry:
+ /* Save boot context and switch to our main context.
+ * Main context is statically defined in C.
+ */
+ pushl %cs
+ call __switch_context
+
+ /* We get here when the main context switches back to
+ * the boot context.
+ * Return to previous bootloader.
+ */
+ ret
+
+/*
+ * Switch execution context
+ * This saves registers, segments, and GDT in the stack, then
+ * switches the stack, and restores everything from the new stack.
+ * This function takes no argument. New stack pointer is
+ * taken from global variable __context, and old stack pointer
+ * is also saved to __context. This way we can just jump to
+ * this routine to get back to the original context.
+ *
+ * Call this routine with lcall or pushl %cs; call.
+ */
+__switch_context:
+ /* Save everything in current stack */
+ pushfl /* 56 */
+ pushl %ds /* 52 */
+ pushl %es /* 48 */
+ pushl %fs /* 44 */
+ pushl %gs /* 40 */
+ pushal /* 8 */
+ subl $8, %esp
+ movw %ss, (%esp) /* 0 */
+ sgdt 2(%esp) /* 2 */
+
+#if 0
+ /* Swap %cs and %eip on the stack, so lret will work */
+ movl 60(%esp), %eax
+ xchgl %eax, 64(%esp)
+ movl %eax, 60(%esp)
+#endif
+
+ /* At this point we don't know if we are on flat segment
+ * or relocated. So compute the address offset from %eip.
+ * Assuming CS.base==DS.base==SS.base.
+ */
+ call 1f
+1: popl %ebx
+ subl $1b, %ebx
+
+ /* Interrupts are not allowed... */
+ cli
+
+ /* Current context pointer is our stack pointer */
+ movl %esp, %esi
+
+ /* Normalize the ctx pointer */
+ subl %ebx, %esi
+
+ /* Swap it with new value */
+ xchgl %esi, __context(%ebx)
+
+ /* Adjust new ctx pointer for current address offset */
+ addl %ebx, %esi
+
+ /* Load new %ss and %esp to temporary */
+ movzwl (%esi), %edx
+ movl 20(%esi), %eax
+
+ /* Load new GDT */
+ lgdt 2(%esi)
+
+ /* Load new stack segment with new GDT */
+ movl %edx, %ss
+
+ /* Set new stack pointer, but we have to adjust it because
+ * pushal saves %esp value before pushal, and we want the value
+ * after pushal.
+ */
+ leal -32(%eax), %esp
+
+ /* Load the rest from new stack */
+ popal
+ popl %gs
+ popl %fs
+ popl %es
+ popl %ds
+ popfl
+
+ /* Finally, load new %cs and %eip */
+ lret
+
+__exit_context:
+ /* Get back to the original context */
+ pushl %cs
+ call __switch_context
+
+ /* We get here if the other context attempt to switch to this
+ * dead context. This should not happen. */
+
+halt:
+ cli
+ hlt
+ jmp halt
+
+/*
+ * initialize exception handler. All exceptions end up in the same
+ * C function.
+ */
+
+init_exceptions:
+ pushl %ebx
+ pushl %edi
+
+ /* Initialize the Interrupt Descriptor table */
+ leal _idt, %edi
+ leal vec0, %ebx
+ movl $(0x08 << 16), %eax /* cs selector */
+
+1: movw %bx, %ax
+ movl %ebx, %edx
+ movw $0x8E00, %dx /* Interrupt gate - dpl=0, present */
+ movl %eax, 0(%edi)
+ movl %edx, 4(%edi)
+ addl $6, %ebx
+ addl $8, %edi
+ cmpl $_idt_end, %edi
+ jne 1b
+
+ /* Load the Interrupt descriptor table */
+ lidt idtarg
+
+ movl $0, %eax
+ popl %edi
+ popl %ebx
+ ret
+
+vec0:
+ pushl $0 /* error code */
+ pushl $0 /* vector */
+ jmp int_hand
+vec1:
+ pushl $0 /* error code */
+ pushl $1 /* vector */
+ jmp int_hand
+
+vec2:
+ pushl $0 /* error code */
+ pushl $2 /* vector */
+ jmp int_hand
+
+vec3:
+ pushl $0 /* error code */
+ pushl $3 /* vector */
+ jmp int_hand
+
+vec4:
+ pushl $0 /* error code */
+ pushl $4 /* vector */
+ jmp int_hand
+
+vec5:
+ pushl $0 /* error code */
+ pushl $5 /* vector */
+ jmp int_hand
+
+vec6:
+ pushl $0 /* error code */
+ pushl $6 /* vector */
+ jmp int_hand
+vec7:
+ pushl $0 /* error code */
+ pushl $7 /* vector */
+ jmp int_hand
+
+vec8:
+ /* error code */
+ pushl $8 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec9:
+ pushl $0 /* error code */
+ pushl $9 /* vector */
+ jmp int_hand
+
+vec10:
+ /* error code */
+ pushl $10 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec11:
+ /* error code */
+ pushl $11 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec12:
+ /* error code */
+ pushl $12 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec13:
+ /* error code */
+ pushl $13 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec14:
+ /* error code */
+ pushl $14 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec15:
+ pushl $0 /* error code */
+ pushl $15 /* vector */
+ jmp int_hand
+
+vec16:
+ pushl $0 /* error code */
+ pushl $16 /* vector */
+ jmp int_hand
+
+vec17:
+ /* error code */
+ pushl $17 /* vector */
+ jmp int_hand
+ .word 0x9090
+
+vec18:
+ pushl $0 /* error code */
+ pushl $18 /* vector */
+ jmp int_hand
+
+vec19:
+ pushl $0 /* error code */
+ pushl $19 /* vector */
+ jmp int_hand
+
+__divide_error:
+ pushl $0 /* error code */
+ pushl $20 /* vector */
+ jmp int_hand
+ .global __divide_error
+
+int_hand:
+ /* At this point on the stack there is:
+ * 0(%esp) vector
+ * 4(%esp) error code
+ * 8(%esp) eip
+ * 12(%esp) cs
+ * 16(%esp) eflags
+ */
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+ /* Original stack pointer */
+ leal 32(%esp), %ebp
+ pushl %ebp
+ pushl %ebx
+ pushl %edx
+ pushl %ecx
+ pushl %eax
+
+ pushl %esp /* Pointer to structure on the stack */
+
+ call x86_exception
+ pop %eax /* Drop the pointer */
+
+ popl %eax
+ popl %ecx
+ popl %edx
+ popl %ebx
+ popl %ebp /* Ignore saved %esp value */
+ popl %ebp
+ popl %esi
+ popl %edi
+
+ addl $8, %esp /* pop of the vector and error code */
+
+ iret
+
+idtarg:
+ .word _idt_end - _idt - 1 /* limit */
+ .long _idt
+ .word 0
+_idt:
+ .fill 20, 8, 0 # idt is unitiailzed
+_idt_end:
+
+ .globl arch_nvram_size, arch_nvram_get, arch_nvram_put
+arch_nvram_size:
+ xor %eax, %eax
+ ret
+
+arch_nvram_get:
+ ret
+
+arch_nvram_put:
+ ret