summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/efi/efi.c27
-rw-r--r--include/linux/efi.h31
2 files changed, 48 insertions, 10 deletions
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 7dbe1487b111..703a019d81b4 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -34,6 +34,7 @@
#include <asm/early_ioremap.h>
struct efi __read_mostly efi = {
+ .runtime_supported_mask = EFI_RT_SUPPORTED_ALL,
.acpi = EFI_INVALID_TABLE_ADDR,
.acpi20 = EFI_INVALID_TABLE_ADDR,
.smbios = EFI_INVALID_TABLE_ADDR,
@@ -301,16 +302,22 @@ static int __init efisubsys_init(void)
if (!efi_enabled(EFI_BOOT))
return 0;
- /*
- * Since we process only one efi_runtime_service() at a time, an
- * ordered workqueue (which creates only one execution context)
- * should suffice all our needs.
- */
- efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0);
- if (!efi_rts_wq) {
- pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
- clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
- return 0;
+ if (!efi_enabled(EFI_RUNTIME_SERVICES))
+ efi.runtime_supported_mask = 0;
+
+ if (efi.runtime_supported_mask) {
+ /*
+ * Since we process only one efi_runtime_service() at a time, an
+ * ordered workqueue (which creates only one execution context)
+ * should suffice for all our needs.
+ */
+ efi_rts_wq = alloc_ordered_workqueue("efi_rts_wq", 0);
+ if (!efi_rts_wq) {
+ pr_err("Creating efi_rts_wq failed, EFI runtime services disabled.\n");
+ clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
+ efi.runtime_supported_mask = 0;
+ return 0;
+ }
}
/* We register the efi directory at /sys/firmware/efi */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index a0008e3d4e9d..57695f400044 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -523,6 +523,7 @@ typedef struct {
extern struct efi {
const efi_runtime_services_t *runtime; /* EFI runtime services table */
unsigned int runtime_version; /* Runtime services version */
+ unsigned int runtime_supported_mask;
unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
unsigned long acpi20; /* ACPI table (ACPI 2.0) */
@@ -551,6 +552,26 @@ extern struct efi {
unsigned long flags;
} efi;
+#define EFI_RT_SUPPORTED_GET_TIME 0x0001
+#define EFI_RT_SUPPORTED_SET_TIME 0x0002
+#define EFI_RT_SUPPORTED_GET_WAKEUP_TIME 0x0004
+#define EFI_RT_SUPPORTED_SET_WAKEUP_TIME 0x0008
+#define EFI_RT_SUPPORTED_GET_VARIABLE 0x0010
+#define EFI_RT_SUPPORTED_GET_NEXT_VARIABLE_NAME 0x0020
+#define EFI_RT_SUPPORTED_SET_VARIABLE 0x0040
+#define EFI_RT_SUPPORTED_SET_VIRTUAL_ADDRESS_MAP 0x0080
+#define EFI_RT_SUPPORTED_CONVERT_POINTER 0x0100
+#define EFI_RT_SUPPORTED_GET_NEXT_HIGH_MONOTONIC_COUNT 0x0200
+#define EFI_RT_SUPPORTED_RESET_SYSTEM 0x0400
+#define EFI_RT_SUPPORTED_UPDATE_CAPSULE 0x0800
+#define EFI_RT_SUPPORTED_QUERY_CAPSULE_CAPABILITIES 0x1000
+#define EFI_RT_SUPPORTED_QUERY_VARIABLE_INFO 0x2000
+
+#define EFI_RT_SUPPORTED_ALL 0x3fff
+
+#define EFI_RT_SUPPORTED_TIME_SERVICES 0x000f
+#define EFI_RT_SUPPORTED_VARIABLE_SERVICES 0x0070
+
extern struct mm_struct efi_mm;
static inline int
@@ -761,6 +782,11 @@ static inline bool __pure efi_soft_reserve_enabled(void)
return IS_ENABLED(CONFIG_EFI_SOFT_RESERVE)
&& __efi_soft_reserve_enabled();
}
+
+static inline bool efi_rt_services_supported(unsigned int mask)
+{
+ return (efi.runtime_supported_mask & mask) == mask;
+}
#else
static inline bool efi_enabled(int feature)
{
@@ -779,6 +805,11 @@ static inline bool efi_soft_reserve_enabled(void)
{
return false;
}
+
+static inline bool efi_rt_services_supported(unsigned int mask)
+{
+ return false;
+}
#endif
extern int efi_status_to_err(efi_status_t status);