]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/platform/efi/efi.c
Merge branch 'master' into x86/memblock
[karo-tx-linux.git] / arch / x86 / platform / efi / efi.c
index 3b4e86bda3cb9fc667dbf892af0f50e5bfd28c0c..4a01967f02e76c5d0156e35b94ef303162d661e6 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/efi.h>
+#include <linux/export.h>
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/spinlock.h>
 int efi_enabled;
 EXPORT_SYMBOL(efi_enabled);
 
-struct efi efi;
+struct efi __read_mostly efi = {
+       .mps        = EFI_INVALID_TABLE_ADDR,
+       .acpi       = EFI_INVALID_TABLE_ADDR,
+       .acpi20     = EFI_INVALID_TABLE_ADDR,
+       .smbios     = EFI_INVALID_TABLE_ADDR,
+       .sal_systab = EFI_INVALID_TABLE_ADDR,
+       .boot_info  = EFI_INVALID_TABLE_ADDR,
+       .hcdp       = EFI_INVALID_TABLE_ADDR,
+       .uga        = EFI_INVALID_TABLE_ADDR,
+       .uv_systab  = EFI_INVALID_TABLE_ADDR,
+};
 EXPORT_SYMBOL(efi);
 
 struct efi_memory_map memmap;
@@ -79,26 +90,50 @@ early_param("add_efi_memmap", setup_add_efi_memmap);
 
 static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
 {
-       return efi_call_virt2(get_time, tm, tc);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt2(get_time, tm, tc);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_time(efi_time_t *tm)
 {
-       return efi_call_virt1(set_time, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt1(set_time, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
                                             efi_bool_t *pending,
                                             efi_time_t *tm)
 {
-       return efi_call_virt3(get_wakeup_time,
-                             enabled, pending, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt3(get_wakeup_time,
+                               enabled, pending, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
 {
-       return efi_call_virt2(set_wakeup_time,
-                             enabled, tm);
+       unsigned long flags;
+       efi_status_t status;
+
+       spin_lock_irqsave(&rtc_lock, flags);
+       status = efi_call_virt2(set_wakeup_time,
+                               enabled, tm);
+       spin_unlock_irqrestore(&rtc_lock, flags);
+       return status;
 }
 
 static efi_status_t virt_efi_get_variable(efi_char16_t *name,
@@ -122,7 +157,7 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
 
 static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                                          efi_guid_t *vendor,
-                                         unsigned long attr,
+                                         u32 attr,
                                          unsigned long data_size,
                                          void *data)
 {
@@ -131,6 +166,18 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
                              data_size, data);
 }
 
+static efi_status_t virt_efi_query_variable_info(u32 attr,
+                                                u64 *storage_space,
+                                                u64 *remaining_space,
+                                                u64 *max_variable_size)
+{
+       if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+
+       return efi_call_virt4(query_variable_info, attr, storage_space,
+                             remaining_space, max_variable_size);
+}
+
 static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
 {
        return efi_call_virt1(get_next_high_mono_count, count);
@@ -145,6 +192,28 @@ static void virt_efi_reset_system(int reset_type,
                       data_size, data);
 }
 
+static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
+                                           unsigned long count,
+                                           unsigned long sg_list)
+{
+       if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+
+       return efi_call_virt3(update_capsule, capsules, count, sg_list);
+}
+
+static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
+                                               unsigned long count,
+                                               u64 *max_size,
+                                               int *reset_type)
+{
+       if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+               return EFI_UNSUPPORTED;
+
+       return efi_call_virt4(query_capsule_caps, capsules, count, max_size,
+                             reset_type);
+}
+
 static efi_status_t __init phys_efi_set_virtual_address_map(
        unsigned long memory_map_size,
        unsigned long descriptor_size,
@@ -164,11 +233,14 @@ static efi_status_t __init phys_efi_set_virtual_address_map(
 static efi_status_t __init phys_efi_get_time(efi_time_t *tm,
                                             efi_time_cap_t *tc)
 {
+       unsigned long flags;
        efi_status_t status;
 
+       spin_lock_irqsave(&rtc_lock, flags);
        efi_call_phys_prelog();
        status = efi_call_phys2(efi_phys.get_time, tm, tc);
        efi_call_phys_epilog();
+       spin_unlock_irqrestore(&rtc_lock, flags);
        return status;
 }
 
@@ -666,6 +738,9 @@ void __init efi_enter_virtual_mode(void)
        efi.get_next_high_mono_count = virt_efi_get_next_high_mono_count;
        efi.reset_system = virt_efi_reset_system;
        efi.set_virtual_address_map = NULL;
+       efi.query_variable_info = virt_efi_query_variable_info;
+       efi.update_capsule = virt_efi_update_capsule;
+       efi.query_capsule_caps = virt_efi_query_capsule_caps;
        if (__supported_pte_mask & _PAGE_NX)
                runtime_code_page_mkexec();
        early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);