x86, oprom: ensure DF is always cleared

The Option ROM might mess with the EFLAGS register and break assumptions
the C part of coreboot implicitly has, e.g. the state of the direction
flag.

Prevent Option ROMs from confusing coreboot by restoring the old EFLAGS
value after the Option ROMs has finished and always clear the direction
flag before calling the C part of the interrupt handler.

Change-Id: I84663be6681b17f95f48d93f0b730e443336b4a8
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Reviewed-on: http://review.coreboot.org/837
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
This commit is contained in:
Mathias Krause 2012-04-01 11:32:09 +02:00 committed by Stefan Reinauer
parent 74a0efe09a
commit 971804ed68
1 changed files with 38 additions and 29 deletions

View File

@ -75,35 +75,36 @@ __buffer = RELOCATED(.)
.globl __realmode_call .globl __realmode_call
__realmode_call = RELOCATED(.) __realmode_call = RELOCATED(.)
/* save all registers to the stack */ /* save all registers to the stack */
pushal pusha
pushf
/* Move the protected mode stack to a safe place */ /* Move the protected mode stack pointer to a safe place */
movl %esp, __stack movl %esp, __stack
movl %esp, %ebp movl %esp, %ebp
/* This function is called with regparm=0 and we have /* This function is called with regparm=0 and we have to
* to skip the 32 byte from pushal. Hence start at 36. * skip the 36 byte from pushf+pusha. Hence start at 40.
*/ */
/* entry point */ /* entry point */
movl 36(%ebp), %eax movl 40(%ebp), %eax
mov %ax, __lcall_instr + 1 mov %ax, __lcall_instr + 1
andl $0xffff0000, %eax andl $0xffff0000, %eax
shrl $4, %eax shrl $4, %eax
mov %ax, __lcall_instr + 3 mov %ax, __lcall_instr + 3
/* initial register values */ /* initial register values */
movl 40(%ebp), %eax
movl %eax, __registers + 0 /* eax */
movl 44(%ebp), %eax movl 44(%ebp), %eax
movl %eax, __registers + 4 /* ebx */ movl %eax, __registers + 0 /* eax */
movl 48(%ebp), %eax movl 48(%ebp), %eax
movl %eax, __registers + 8 /* ecx */ movl %eax, __registers + 4 /* ebx */
movl 52(%ebp), %eax movl 52(%ebp), %eax
movl %eax, __registers + 12 /* edx */ movl %eax, __registers + 8 /* ecx */
movl 56(%ebp), %eax movl 56(%ebp), %eax
movl %eax, __registers + 16 /* esi */ movl %eax, __registers + 12 /* edx */
movl 60(%ebp), %eax movl 60(%ebp), %eax
movl %eax, __registers + 16 /* esi */
movl 64(%ebp), %eax
movl %eax, __registers + 20 /* edi */ movl %eax, __registers + 20 /* edi */
/* Activate the right segment descriptor real mode. */ /* Activate the right segment descriptor real mode. */
@ -193,41 +194,45 @@ __lcall_instr = RELOCATED(.)
/* restore proper idt */ /* restore proper idt */
lidt idtarg lidt idtarg
/* and exit */ /* restore stack pointer, eflags and register values */
movl __stack, %esp movl __stack, %esp
popal popf
popa
/* and exit */
// TODO return AX from OPROM call // TODO return AX from OPROM call
ret ret
.globl __realmode_interrupt .globl __realmode_interrupt
__realmode_interrupt = RELOCATED(.) __realmode_interrupt = RELOCATED(.)
/* save all registers to the stack */ /* save all registers to the stack */
pushal pusha
/* save the stack */ pushf
movl %esp, __stack
movl %esp, %ebp
/* This function is called with regparm=0 and we have /* save the stack pointer */
* to skip the 32 byte from pushal. Hence start at 36. movl %esp, __stack
movl %esp, %ebp
/* This function is called with regparm=0 and we have to
* skip the 36 byte from pushf+pusha. Hence start at 40.
*/ */
/* prepare interrupt calling code */ /* prepare interrupt calling code */
movl 36(%ebp), %eax movl 40(%ebp), %eax
movb %al, __intXX_instr + 1 /* intno */ movb %al, __intXX_instr + 1 /* intno */
/* initial register values */ /* initial register values */
movl 40(%ebp), %eax
movl %eax, __registers + 0 /* eax */
movl 44(%ebp), %eax movl 44(%ebp), %eax
movl %eax, __registers + 4 /* ebx */ movl %eax, __registers + 0 /* eax */
movl 48(%ebp), %eax movl 48(%ebp), %eax
movl %eax, __registers + 8 /* ecx */ movl %eax, __registers + 4 /* ebx */
movl 52(%ebp), %eax movl 52(%ebp), %eax
movl %eax, __registers + 12 /* edx */ movl %eax, __registers + 8 /* ecx */
movl 56(%ebp), %eax movl 56(%ebp), %eax
movl %eax, __registers + 16 /* esi */ movl %eax, __registers + 12 /* edx */
movl 60(%ebp), %eax movl 60(%ebp), %eax
movl %eax, __registers + 16 /* esi */
movl 64(%ebp), %eax
movl %eax, __registers + 20 /* edi */ movl %eax, __registers + 20 /* edi */
/* This configures CS properly for real mode. */ /* This configures CS properly for real mode. */
@ -309,9 +314,10 @@ __intXX_instr = RELOCATED(.)
/* restore coreboot's 32-bit IDT */ /* restore coreboot's 32-bit IDT */
lidt idtarg lidt idtarg
/* Exit */ /* restore stack pointer, eflags and register values and exit */
movl __stack, %esp movl __stack, %esp
popal popf
popa
ret ret
/* This is the 16-bit interrupt entry point called by the IDT stub code. /* This is the 16-bit interrupt entry point called by the IDT stub code.
@ -327,6 +333,9 @@ __interrupt_handler_16bit = RELOCATED(.)
push %fs push %fs
push %gs push %gs
/* Clear DF to not break ABI assumptions */
cld
/* Clean up the interrupt number. We could have done this in the stub, /* Clean up the interrupt number. We could have done this in the stub,
* but it would have cost 2 more bytes per stub entry. * but it would have cost 2 more bytes per stub entry.
*/ */