aboutsummaryrefslogtreecommitdiffstats
path: root/roms/qboot/entry.S
diff options
context:
space:
mode:
Diffstat (limited to 'roms/qboot/entry.S')
-rw-r--r--roms/qboot/entry.S138
1 files changed, 138 insertions, 0 deletions
diff --git a/roms/qboot/entry.S b/roms/qboot/entry.S
new file mode 100644
index 000000000..31d840bac
--- /dev/null
+++ b/roms/qboot/entry.S
@@ -0,0 +1,138 @@
+/*
+ * Our pretty trivial BIOS emulation
+ */
+
+#include "assembly.h"
+#include "processor-flags.h"
+
+ .org 0
+ .code16gcc
+
+/*
+ * handy BIOS macros
+ */
+
+/* If you change these macros, remember to update 'struct biosregs' */
+.macro SAVE_BIOSREGS
+ pushl %fs
+ pushl %es
+ pushl %ds
+ pushl %edi
+ pushl %esi
+ pushl %ebp
+ pushl %esp
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+ pushl %eax
+.endm
+
+.macro RESTORE_BIOSREGS
+ popl %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esp
+ popl %ebp
+ popl %esi
+ popl %edi
+ popl %ds
+ popl %es
+ popl %fs
+.endm
+
+ENTRY(bios_irq)
+ pushw %ax
+ mov $0x20, %al
+ out %al, $0x20
+ popw %ax
+ IRET
+ENTRY_END(bios_irq)
+
+/*
+ * fake interrupt handler, nothing can be faster ever
+ */
+ENTRY(bios_intfake)
+ /*
+ * Set CF to indicate failure. We don't want callers to think that the
+ * interrupt handler succeeded and then treat the return values in
+ * registers as valid data.
+ */
+ orb $X86_EFLAGS_CF, 0x4(%esp)
+
+ IRET
+ENTRY_END(bios_intfake)
+
+/*
+ * int 10 - video - service
+ */
+ENTRY(bios_int10)
+ andb $~X86_EFLAGS_CF, 0x4(%esp)
+ SAVE_BIOSREGS
+
+ movl %esp, %eax
+ /* this is way easier than doing it in assembly */
+ /* just push all the regs and jump to a C handler */
+ call int10_handler
+
+ RESTORE_BIOSREGS
+
+ IRET
+ENTRY_END(bios_int10)
+
+ENTRY(bios_int15)
+ andb $~X86_EFLAGS_CF, 0x4(%esp)
+ SAVE_BIOSREGS
+
+ movl %esp, %eax
+ call int15_handler
+
+ RESTORE_BIOSREGS
+
+ IRET
+ENTRY_END(bios_int15)
+
+ .code32
+ENTRY(pcibios_entry)
+ clc
+ pushfl
+ SAVE_BIOSREGS
+
+ movl %esp, %eax
+ call pcibios_handler
+
+ RESTORE_BIOSREGS
+ popfl
+ lretl
+ENTRY_END(pcibios_entry)
+
+ENTRY(bios32_entry)
+ pushfl
+ testl %ebx, %ebx /* BIOS32 service directory? */
+ jnz 2f
+ cmp $0x49435024, %eax /* "$PCI"? */
+ movb $0x80, %al /* service not present */
+ jne 1f
+ xorl %ebx, %ebx /* fill in base/length/entry */
+ movl $(1 << 20), %ecx
+ movl $pcibios_entry, %edx
+ movb $0x00, %al /* service present */
+1:
+ popfl
+ lretl
+2:
+ movb $0x81, %al /* unimplemented function */
+ popfl
+ lretl
+ENTRY_END(bios32_entry)
+
+ENTRY(pic_base)
+ call 1f
+2:
+ ret
+1:
+ popl %eax
+ pushl %eax
+ subl $2b, %eax
+ ret /* return to 2b */
+ENTRY_END(pic_base)