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