efi_stub_32.S 2.3 KB

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