efi_stub_32.S 2.3 KB

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