* Copyright (c) Russ Anderson <rja@sgi.com>
  */
 
+#include <linux/efi.h>
 #include <linux/rtc.h>
 
 /*
 struct uv_systab {
        char signature[4];      /* must be UV_SYSTAB_SIG */
        u32 revision;           /* distinguish different firmware revs */
-       u64 function;           /* BIOS runtime callback function ptr */
+       u64 (__efiapi *function)(enum uv_bios_cmd, ...);
+                               /* BIOS runtime callback function ptr */
        u32 size;               /* systab size (starting with _VERSION_UV4) */
        struct {
                u32 type:8;     /* type of entry */
 
  */
 #define efi_call_virt(f, args...)   \
        efi_call_virt_pointer(efi.runtime, f, args)
-#define __efi_call_virt(f, args...) \
-       __efi_call_virt_pointer(efi.runtime, f, args)
 
 union efi_rts_args {
        struct {
                        "could not get exclusive access to the firmware\n");
                return;
        }
+
+       arch_efi_call_virt_setup();
        efi_rts_work.efi_rts_id = EFI_RESET_SYSTEM;
-       __efi_call_virt(reset_system, reset_type, status, data_size, data);
+       arch_efi_call_virt(efi.runtime, reset_system, reset_type, status,
+                          data_size, data);
+       arch_efi_call_virt_teardown();
+
        up(&efi_runtime_lock);
 }
 
 
 #define arch_efi_call_virt(p, f, args...)      ((p)->f(args))
 
 /*
- * Arch code can implement the following three template macros, avoiding
- * reptition for the void/non-void return cases of {__,}efi_call_virt():
+ * Arch code must implement the following three routines:
  *
  *  * arch_efi_call_virt_setup()
  *
  *
  *  * arch_efi_call_virt()
  *
- *    Performs the call. The last expression in the macro must be the call
- *    itself, allowing the logic to be shared by the void and non-void
- *    cases.
+ *    Performs the call. This routine takes a variable number of arguments so
+ *    it must be implemented as a variadic preprocessor macro.
  *
  *  * arch_efi_call_virt_teardown()
  *
 
 #define efi_call_virt_pointer(p, f, args...)                           \
 ({                                                                     \
-       efi_status_t __s;                                               \
+       typeof((p)->f(args)) __s;                                       \
        unsigned long __flags;                                          \
                                                                        \
        arch_efi_call_virt_setup();                                     \
        __s;                                                            \
 })
 
-#define __efi_call_virt_pointer(p, f, args...)                         \
-({                                                                     \
-       unsigned long __flags;                                          \
-                                                                       \
-       arch_efi_call_virt_setup();                                     \
-                                                                       \
-       __flags = efi_call_virt_save_flags();                           \
-       arch_efi_call_virt(p, f, args);                                 \
-       efi_call_virt_check_flags(__flags, __stringify(f));             \
-                                                                       \
-       arch_efi_call_virt_teardown();                                  \
-})
-
 #define EFI_RANDOM_SEED_SIZE           32U // BLAKE2S_HASH_SIZE
 
 struct linux_efi_random_seed {