libpayload: x86/exec - simplify and robustify the code

Simplify the code by directly using the arguments on the stack as base
pointer relative memory references, instead of loading them into
intermediate registers first.

Make it more robust by preserving all callee saved registers mandated by
the C calling convention (and only those), namely EBP, EBX, ESI and EDI.

Don't assume anything about the register state when the called function
returns -- beside the segment registers and the stack pointer to be
still the same as before the call.

Change-Id: I383d6ccefc5b3d5cca37a1c9b638c231bbc48aa8
Signed-off-by: Mathias Krause <minipli@googlemail.com>
Reviewed-on: https://review.coreboot.org/18335
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Tested-by: build bot (Jenkins)
This commit is contained in:
Mathias Krause 2017-02-11 21:02:08 +01:00 committed by Martin Roth
parent 7b681c5926
commit 57dc93c967
1 changed files with 20 additions and 39 deletions

View File

@ -37,67 +37,48 @@
.text .text
.global i386_do_exec .global i386_do_exec
.type i386_do_exec,@function .type i386_do_exec,@function
i386_do_exec: i386_do_exec:
pushl %ebp pushl %ebp
movl %esp, %ebp movl %esp, %ebp
pushl %eax
/* Put the run address in %eax */
movl 8(%ebp), %eax
/* Save off the rest of the registers */
/* Save the remaining callee preserved registers */
pushl %ebx
pushl %esi pushl %esi
pushl %ecx pushl %edi
pushl %ebp
/* Push argc and argv on to the stack. /* Push argc and argv on to the stack.
* *
* We need to put a dummy value inbetween, as argc should be at offset * We need to put a dummy value inbetween, as argc should be at offset
* 0x10, according to the payload API. * 0x10, according to the payload API.
*/ */
pushl 12(%ebp)
movl 12(%ebp), %esi
movl 16(%ebp), %ecx
pushl %esi
pushl $0 pushl $0
pushl %ecx pushl 16(%ebp)
/* Move a "magic" number on the stack - the other /* Push a "magic" number on the stack - the other payload will use this
* payload will use this as a clue that the argc * as a clue that the argc and argv values on the stack are sane.
* and argv are sane
*/ */
pushl $0x12345678
movl $0x12345678, %ecx
pushl %ecx
/* Jump to the code */ /* Jump to the code */
call *%eax call *8(%ebp)
/* %eax has the return value */ /* %eax has the return value */
/* Skip over the argc/argv stuff still on the stack */ /* Skip over the argc/argv stuff still on the stack.
addl $12, %esp * Don't assume %ebp is sane, here. Restore it from the stack.
*/
addl $0x10, %esp
/* Get back %ebp */ /* Restore the saved registers */
popl %edi
popl %esi
popl %ebx
popl %ebp popl %ebp
/* Get the pointer to the return value /* Get pointer to return value and save the return value in it. */
* and save the return value in it movl 16(%esp), %ecx
*/
movl 20(%ebp), %ecx
movl %eax, (%ecx) movl %eax, (%ecx)
/* Get the rest of the saved registers */
popl %ecx
popl %esi
popl %eax
/* Restore the stack pointer */
movl %ebp,%esp
popl %ebp
ret ret