/* * 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)