diff --git a/xen/arch/x86/dmi_scan.c b/xen/arch/x86/dmi_scan.c
index b049e31..8dcb640 100644
--- a/xen/arch/x86/dmi_scan.c
+++ b/xen/arch/x86/dmi_scan.c
@@ -238,7 +238,7 @@ const char *__init dmi_get_table(paddr_t *base, u32 *len)
 {
 	static unsigned int __initdata instance;
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		if (efi_smbios3_size && !(instance & 1)) {
 			*base = efi_smbios3_address;
 			*len = efi_smbios3_size;
@@ -696,7 +696,7 @@ static void __init dmi_decode(struct dmi_header *dm)
 
 void __init dmi_scan_machine(void)
 {
-	if ((!efi_enabled ? dmi_iterate(dmi_decode) :
+	if ((!efi_enabled(EFI_BOOT) ? dmi_iterate(dmi_decode) :
 	                    dmi_efi_iterate(dmi_decode)) == 0)
  		dmi_check_system(dmi_blacklist);
 	else
diff --git a/xen/arch/x86/domain_page.c b/xen/arch/x86/domain_page.c
index d86f8fe..a58ef8e 100644
--- a/xen/arch/x86/domain_page.c
+++ b/xen/arch/x86/domain_page.c
@@ -36,7 +36,7 @@ static inline struct vcpu *mapcache_current_vcpu(void)
      * domain's page tables but current may point at another domain's VCPU.
      * Return NULL as though current is not properly set up yet.
      */
-    if ( efi_enabled && efi_rs_using_pgtables() )
+    if ( efi_rs_using_pgtables() )
         return NULL;
 
     /*
diff --git a/xen/arch/x86/efi/stub.c b/xen/arch/x86/efi/stub.c
index 07c2bd0..4158124 100644
--- a/xen/arch/x86/efi/stub.c
+++ b/xen/arch/x86/efi/stub.c
@@ -4,9 +4,10 @@
 #include <xen/lib.h>
 #include <asm/page.h>
 
-#ifndef efi_enabled
-const bool_t efi_enabled = 0;
-#endif
+bool efi_enabled(unsigned int feature)
+{
+    return false;
+}
 
 void __init efi_init_memory(void) { }
 
@@ -14,7 +15,6 @@ void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t l4e) { }
 
 bool_t efi_rs_using_pgtables(void)
 {
-    BUG();
     return 0;
 }
 
diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c
index ef6557c..c3d5bdc 100644
--- a/xen/arch/x86/mpparse.c
+++ b/xen/arch/x86/mpparse.c
@@ -564,7 +564,7 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
 
 static __init void efi_unmap_mpf(void)
 {
-	if (efi_enabled)
+	if (efi_enabled(EFI_BOOT))
 		clear_fixmap(FIX_EFI_MPF);
 }
 
@@ -722,7 +722,7 @@ void __init find_smp_config (void)
 {
 	unsigned int address;
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		efi_check_config();
 		return;
 	}
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index 8ae897a..06f3970 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -439,8 +439,8 @@ static void __init parse_video_info(void)
 {
     struct boot_video_info *bvi = &bootsym(boot_vid_info);
 
-    /* The EFI loader fills vga_console_info directly. */
-    if ( efi_enabled )
+    /* vga_console_info is filled directly on EFI platform. */
+    if ( efi_enabled(EFI_BOOT) )
         return;
 
     if ( (bvi->orig_video_isVGA == 1) && (bvi->orig_video_mode == 3) )
@@ -726,7 +726,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
     if ( !(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0) )
         panic("dom0 kernel not specified. Check bootloader configuration.");
 
-    if ( efi_enabled )
+    if ( efi_enabled(EFI_LOADER) )
     {
         set_pdx_range(xen_phys_start >> PAGE_SHIFT,
                       (xen_phys_start + BOOTSTRAP_MAP_BASE) >> PAGE_SHIFT);
@@ -741,6 +741,8 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
         memmap_type = loader;
     }
+    else if ( efi_enabled(EFI_BOOT) )
+        memmap_type = "EFI";
     else if ( e820_raw_nr != 0 )
     {
         memmap_type = "Xen-e820";
@@ -837,7 +839,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
      * we can relocate the dom0 kernel and other multiboot modules. Also, on
      * x86/64, we relocate Xen to higher memory.
      */
-    for ( i = 0; !efi_enabled && i < mbi->mods_count; i++ )
+    for ( i = 0; !efi_enabled(EFI_LOADER) && i < mbi->mods_count; i++ )
     {
         if ( mod[i].mod_start & (PAGE_SIZE - 1) )
             panic("Bootloader didn't honor module alignment request.");
@@ -1078,7 +1080,7 @@ void __init noreturn __start_xen(unsigned long mbi_p)
 
     if ( !xen_phys_start )
         panic("Not enough memory to relocate Xen.");
-    reserve_e820_ram(&boot_e820, efi_enabled ? mbi->mem_upper : __pa(&_start),
+    reserve_e820_ram(&boot_e820, efi_enabled(EFI_LOADER) ? mbi->mem_upper : __pa(&_start),
                      __pa(&_end));
 
     /* Late kexec reservation (dynamic start address). */
diff --git a/xen/arch/x86/shutdown.c b/xen/arch/x86/shutdown.c
index 0e1499d..54c2c79 100644
--- a/xen/arch/x86/shutdown.c
+++ b/xen/arch/x86/shutdown.c
@@ -116,7 +116,7 @@ void machine_halt(void)
 static void default_reboot_type(void)
 {
     if ( reboot_type == BOOT_INVALID )
-        reboot_type = efi_enabled ? BOOT_EFI
+        reboot_type = efi_enabled(EFI_RS) ? BOOT_EFI
                                   : acpi_disabled ? BOOT_KBD
                                                   : BOOT_ACPI;
 }
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index 73e0f98..f043998 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -727,7 +727,7 @@ static unsigned long get_cmos_time(void)
     static bool_t __read_mostly cmos_rtc_probe;
     boolean_param("cmos-rtc-probe", cmos_rtc_probe);
 
-    if ( efi_enabled )
+    if ( efi_enabled(EFI_RS) )
     {
         res = efi_get_time();
         if ( res )
diff --git a/xen/common/efi/boot.c b/xen/common/efi/boot.c
index 125c9ce..56544dc 100644
--- a/xen/common/efi/boot.c
+++ b/xen/common/efi/boot.c
@@ -934,6 +934,13 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
     char *option_str;
     bool_t use_cfg_file;
 
+    __set_bit(EFI_BOOT, &efi_flags);
+    __set_bit(EFI_LOADER, &efi_flags);
+
+#ifndef CONFIG_ARM /* Disabled until runtime services implemented. */
+    __set_bit(EFI_RS, &efi_flags);
+#endif
+
     efi_init(ImageHandle, SystemTable);
 
     use_cfg_file = efi_arch_use_config_file(SystemTable);
@@ -1153,7 +1160,6 @@ efi_start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
 
 #ifndef CONFIG_ARM /* TODO - runtime service support */
 
-static bool_t __initdata efi_rs_enable = 1;
 static bool_t __initdata efi_map_uc;
 
 static void __init parse_efi_param(char *s)
@@ -1171,7 +1177,12 @@ static void __init parse_efi_param(char *s)
             *ss = '\0';
 
         if ( !strcmp(s, "rs") )
-            efi_rs_enable = val;
+        {
+            if ( val )
+                __set_bit(EFI_RS, &efi_flags);
+            else
+                __clear_bit(EFI_RS, &efi_flags);
+        }
         else if ( !strcmp(s, "attr=uc") )
             efi_map_uc = val;
 
@@ -1254,7 +1265,7 @@ void __init efi_init_memory(void)
                desc->PhysicalStart, desc->PhysicalStart + len - 1,
                desc->Type, desc->Attribute);
 
-        if ( !efi_rs_enable ||
+        if ( !efi_enabled(EFI_RS) ||
              (!(desc->Attribute & EFI_MEMORY_RUNTIME) &&
               (!map_bs ||
                (desc->Type != EfiBootServicesCode &&
@@ -1328,7 +1339,7 @@ void __init efi_init_memory(void)
         }
     }
 
-    if ( !efi_rs_enable )
+    if ( !efi_enabled(EFI_RS) )
     {
         efi_fw_vendor = NULL;
         return;
diff --git a/xen/common/efi/runtime.c b/xen/common/efi/runtime.c
index c256814..5f2de80 100644
--- a/xen/common/efi/runtime.c
+++ b/xen/common/efi/runtime.c
@@ -10,12 +10,6 @@ DEFINE_XEN_GUEST_HANDLE(CHAR16);
 
 #ifndef COMPAT
 
-/*
- * Currently runtime services are not implemented on ARM. To boot Xen with ACPI,
- * set efi_enabled to 1, so that Xen can get the ACPI root pointer from EFI.
- */
-const bool_t efi_enabled = 1;
-
 #ifndef CONFIG_ARM
 # include <asm/i387.h>
 # include <asm/xstate.h>
@@ -43,6 +37,9 @@ UINT64 __read_mostly efi_boot_max_var_store_size;
 UINT64 __read_mostly efi_boot_remain_var_store_size;
 UINT64 __read_mostly efi_boot_max_var_size;
 
+/* Bit field representing available EFI features/properties. */
+unsigned int efi_flags;
+
 struct efi __read_mostly efi = {
 	.acpi   = EFI_INVALID_TABLE_ADDR,
 	.acpi20 = EFI_INVALID_TABLE_ADDR,
@@ -53,6 +50,11 @@ struct efi __read_mostly efi = {
 
 const struct efi_pci_rom *__read_mostly efi_pci_roms;
 
+bool efi_enabled(unsigned int feature)
+{
+    return test_bit(feature, &efi_flags);
+}
+
 #ifndef CONFIG_ARM /* TODO - disabled until implemented on ARM */
 unsigned long efi_rs_enter(void)
 {
diff --git a/xen/common/version.c b/xen/common/version.c
index 0d31e38..223cb52 100644
--- a/xen/common/version.c
+++ b/xen/common/version.c
@@ -160,7 +160,7 @@ static int __init xen_build_init(void)
 
 #ifdef CONFIG_X86
     /* Alternatively we may have a CodeView record from an EFI build. */
-    if ( rc && efi_enabled )
+    if ( rc && efi_enabled(EFI_LOADER) )
     {
         const struct pe_external_debug_directory *dir = (const void *)n;
 
diff --git a/xen/drivers/acpi/osl.c b/xen/drivers/acpi/osl.c
index 9a49029..3616dfd 100644
--- a/xen/drivers/acpi/osl.c
+++ b/xen/drivers/acpi/osl.c
@@ -66,7 +66,7 @@ void __init acpi_os_vprintf(const char *fmt, va_list args)
 
 acpi_physical_address __init acpi_os_get_root_pointer(void)
 {
-	if (efi_enabled) {
+	if (efi_enabled(EFI_BOOT)) {
 		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
 			return efi.acpi20;
 		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
diff --git a/xen/include/xen/efi.h b/xen/include/xen/efi.h
index e74dad1..68c68a8 100644
--- a/xen/include/xen/efi.h
+++ b/xen/include/xen/efi.h
@@ -5,10 +5,13 @@
 #include <xen/types.h>
 #endif
 
-extern const bool_t efi_enabled;
-
 #define EFI_INVALID_TABLE_ADDR (~0UL)
 
+extern unsigned int efi_flags;
+#define EFI_BOOT	0	/* Were we booted from EFI? */
+#define EFI_LOADER	1	/* Were we booted directly from EFI loader? */
+#define EFI_RS		2	/* Can we use runtime services? */
+
 /* Add fields here only if they need to be referenced from non-EFI code. */
 struct efi {
     unsigned long mps;          /* MPS table */
@@ -28,6 +31,7 @@ union compat_pf_efi_info;
 struct xenpf_efi_runtime_call;
 struct compat_pf_efi_runtime_call;
 
+bool efi_enabled(unsigned int feature);
 void efi_init_memory(void);
 bool_t efi_rs_using_pgtables(void);
 unsigned long efi_get_time(void);
