linux/arch/x86/boot/compressed/efi_stub_32.S
<<
>>
Prefs
   1/*
   2 * EFI call stub for IA32.
   3 *
   4 * This stub allows us to make EFI calls in physical mode with interrupts
   5 * turned off. Note that this implementation is different from the one in
   6 * arch/x86/platform/efi/efi_stub_32.S because we're _already_ in physical
   7 * mode at this point.
   8 */
   9
  10#include <linux/linkage.h>
  11#include <asm/page_types.h>
  12
  13/*
  14 * efi_call_phys(void *, ...) is a function with variable parameters.
  15 * All the callers of this function assure that all the parameters are 4-bytes.
  16 */
  17
  18/*
  19 * In gcc calling convention, EBX, ESP, EBP, ESI and EDI are all callee save.
  20 * So we'd better save all of them at the beginning of this function and restore
  21 * at the end no matter how many we use, because we can not assure EFI runtime
  22 * service functions will comply with gcc calling convention, too.
  23 */
  24
  25.text
  26ENTRY(efi_call_phys)
  27        /*
  28         * 0. The function can only be called in Linux kernel. So CS has been
  29         * set to 0x0010, DS and SS have been set to 0x0018. In EFI, I found
  30         * the values of these registers are the same. And, the corresponding
  31         * GDT entries are identical. So I will do nothing about segment reg
  32         * and GDT, but change GDT base register in prelog and epilog.
  33         */
  34
  35        /*
  36         * 1. Because we haven't been relocated by this point we need to
  37         * use relative addressing.
  38         */
  39        call    1f
  401:      popl    %edx
  41        subl    $1b, %edx
  42
  43        /*
  44         * 2. Now on the top of stack is the return
  45         * address in the caller of efi_call_phys(), then parameter 1,
  46         * parameter 2, ..., param n. To make things easy, we save the return
  47         * address of efi_call_phys in a global variable.
  48         */
  49        popl    %ecx
  50        movl    %ecx, saved_return_addr(%edx)
  51        /* get the function pointer into ECX*/
  52        popl    %ecx
  53        movl    %ecx, efi_rt_function_ptr(%edx)
  54
  55        /*
  56         * 3. Call the physical function.
  57         */
  58        call    *%ecx
  59
  60        /*
  61         * 4. Balance the stack. And because EAX contain the return value,
  62         * we'd better not clobber it. We need to calculate our address
  63         * again because %ecx and %edx are not preserved across EFI function
  64         * calls.
  65         */
  66        call    1f
  671:      popl    %edx
  68        subl    $1b, %edx
  69
  70        movl    efi_rt_function_ptr(%edx), %ecx
  71        pushl   %ecx
  72
  73        /*
  74         * 10. Push the saved return address onto the stack and return.
  75         */
  76        movl    saved_return_addr(%edx), %ecx
  77        pushl   %ecx
  78        ret
  79ENDPROC(efi_call_phys)
  80.previous
  81
  82.data
  83saved_return_addr:
  84        .long 0
  85efi_rt_function_ptr:
  86        .long 0
  87