Merge branch 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 31 Jan 2013 06:10:36 +0000 (17:10 +1100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 31 Jan 2013 06:10:36 +0000 (17:10 +1100)
Pull x86 EFI fixes from Peter Anvin:
 "This is a collection of fixes for the EFI support.  The controversial
  bit here is a set of patches which bumps the boot protocol version as
  part of fixing some serious problems with the EFI handover protocol,
  used when booting under EFI using a bootloader as opposed to directly
  from EFI.  These changes should also make it a lot saner to support
  cross-mode 32/64-bit EFI booting in the future.  Getting these changes
  into 3.8 means we avoid presenting an inconsistent ABI to bootloaders.

  Other changes are display detection and fixing efivarfs."

* 'x86-efi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86, efi: remove attribute check from setup_efi_pci
  x86, build: Dynamically find entry points in compressed startup code
  x86, efi: Fix PCI ROM handing in EFI boot stub, in 32-bit mode
  x86, efi: Fix 32-bit EFI handover protocol entry point
  x86, efi: Fix display detection in EFI boot stub
  x86, boot: Define the 2.12 bzImage boot protocol
  x86/boot: Fix minor fd leakage in tools/relocs.c
  x86, efi: Set runtime_version to the EFI spec revision
  x86, efi: fix 32-bit warnings in setup_efi_pci()
  efivarfs: Delete dentry from dcache in efivarfs_file_write()
  efivarfs: Never return ENOENT from firmware
  efi, x86: Pass a proper identity mapping in efi_call_phys_prelog
  efivarfs: Drop link count of the right inode

1  2 
arch/x86/platform/efi/efi.c
drivers/firmware/efivars.c

index 5426e482db6e28bf00945f74f0a9ec4604fd6881,35682489f6d6672025b349d5c0126a3a0611d719..77cf0090c0a3ef7890ea24d4e5e47d1d68e0b024
@@@ -51,6 -51,9 +51,6 @@@
  
  #define EFI_DEBUG     1
  
 -int efi_enabled;
 -EXPORT_SYMBOL(efi_enabled);
 -
  struct efi __read_mostly efi = {
        .mps        = EFI_INVALID_TABLE_ADDR,
        .acpi       = EFI_INVALID_TABLE_ADDR,
@@@ -66,28 -69,19 +66,28 @@@ EXPORT_SYMBOL(efi)
  
  struct efi_memory_map memmap;
  
 -bool efi_64bit;
 -
  static struct efi efi_phys __initdata;
  static efi_system_table_t efi_systab __initdata;
  
  static inline bool efi_is_native(void)
  {
 -      return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
 +      return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
 +}
 +
 +unsigned long x86_efi_facility;
 +
 +/*
 + * Returns 1 if 'facility' is enabled, 0 otherwise.
 + */
 +int efi_enabled(int facility)
 +{
 +      return test_bit(facility, &x86_efi_facility) != 0;
  }
 +EXPORT_SYMBOL(efi_enabled);
  
  static int __init setup_noefi(char *arg)
  {
 -      efi_enabled = 0;
 +      clear_bit(EFI_BOOT, &x86_efi_facility);
        return 0;
  }
  early_param("noefi", setup_noefi);
@@@ -432,7 -426,6 +432,7 @@@ void __init efi_reserve_boot_services(v
  
  void __init efi_unmap_memmap(void)
  {
 +      clear_bit(EFI_MEMMAP, &x86_efi_facility);
        if (memmap.map) {
                early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
                memmap.map = NULL;
@@@ -467,7 -460,7 +467,7 @@@ void __init efi_free_boot_services(void
  
  static int __init efi_systab_init(void *phys)
  {
 -      if (efi_64bit) {
 +      if (efi_enabled(EFI_64BIT)) {
                efi_system_table_64_t *systab64;
                u64 tmp = 0;
  
@@@ -559,7 -552,7 +559,7 @@@ static int __init efi_config_init(u64 t
        void *config_tables, *tablep;
        int i, sz;
  
 -      if (efi_64bit)
 +      if (efi_enabled(EFI_64BIT))
                sz = sizeof(efi_config_table_64_t);
        else
                sz = sizeof(efi_config_table_32_t);
                efi_guid_t guid;
                unsigned long table;
  
 -              if (efi_64bit) {
 +              if (efi_enabled(EFI_64BIT)) {
                        u64 table64;
                        guid = ((efi_config_table_64_t *)tablep)->guid;
                        table64 = ((efi_config_table_64_t *)tablep)->table;
@@@ -691,6 -684,7 +691,6 @@@ void __init efi_init(void
        if (boot_params.efi_info.efi_systab_hi ||
            boot_params.efi_info.efi_memmap_hi) {
                pr_info("Table located above 4GB, disabling EFI.\n");
 -              efi_enabled = 0;
                return;
        }
        efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
                          ((__u64)boot_params.efi_info.efi_systab_hi<<32));
  #endif
  
 -      if (efi_systab_init(efi_phys.systab)) {
 -              efi_enabled = 0;
 +      if (efi_systab_init(efi_phys.systab))
                return;
 -      }
 +
 +      set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
  
        /*
         * Show what we know for posterity
                efi.systab->hdr.revision >> 16,
                efi.systab->hdr.revision & 0xffff, vendor);
  
 -      if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) {
 -              efi_enabled = 0;
 +      if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
                return;
 -      }
 +
 +      set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
  
        /*
         * Note: We currently don't support runtime services on an EFI
  
        if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
 -      else if (efi_runtime_init()) {
 -              efi_enabled = 0;
 -              return;
 +      else {
 +              if (efi_runtime_init())
 +                      return;
 +              set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        }
  
 -      if (efi_memmap_init()) {
 -              efi_enabled = 0;
 +      if (efi_memmap_init())
                return;
 -      }
 +
 +      set_bit(EFI_MEMMAP, &x86_efi_facility);
 +
  #ifdef CONFIG_X86_32
        if (efi_is_native()) {
                x86_platform.get_wallclock = efi_get_time;
@@@ -949,7 -941,7 +949,7 @@@ void __init efi_enter_virtual_mode(void
         *
         * Call EFI services through wrapper functions.
         */
-       efi.runtime_version = efi_systab.fw_revision;
+       efi.runtime_version = efi_systab.hdr.revision;
        efi.get_time = virt_efi_get_time;
        efi.set_time = virt_efi_set_time;
        efi.get_wakeup_time = virt_efi_get_wakeup_time;
@@@ -977,9 -969,6 +977,9 @@@ u32 efi_mem_type(unsigned long phys_add
        efi_memory_desc_t *md;
        void *p;
  
 +      if (!efi_enabled(EFI_MEMMAP))
 +              return 0;
 +
        for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
                md = p;
                if ((md->phys_addr <= phys_addr) &&
index 1065119dff925f98a40fe82f50c18e5cadc33b30,2ed59dc1c48a9bb008143b926242c61aa250cc71..f5596db0cf583dc16226bc629a42977de0f9fa05
@@@ -674,7 -674,7 +674,7 @@@ static int efi_status_to_err(efi_status
                err = -EACCES;
                break;
        case EFI_NOT_FOUND:
-               err = -ENOENT;
+               err = -EIO;
                break;
        default:
                err = -EINVAL;
@@@ -793,6 -793,7 +793,7 @@@ static ssize_t efivarfs_file_write(stru
                spin_unlock(&efivars->lock);
                efivar_unregister(var);
                drop_nlink(inode);
+               d_delete(file->f_dentry);
                dput(file->f_dentry);
  
        } else {
@@@ -994,7 -995,7 +995,7 @@@ static int efivarfs_unlink(struct inod
                list_del(&var->list);
                spin_unlock(&efivars->lock);
                efivar_unregister(var);
-               drop_nlink(dir);
+               drop_nlink(dentry->d_inode);
                dput(dentry);
                return 0;
        }
@@@ -1782,7 -1783,7 +1783,7 @@@ efivars_init(void
        printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
               EFIVARS_DATE);
  
 -      if (!efi_enabled)
 +      if (!efi_enabled(EFI_RUNTIME_SERVICES))
                return 0;
  
        /* For now we'll register the efi directory at /sys/firmware/efi */
@@@ -1822,7 -1823,7 +1823,7 @@@ err_put
  static void __exit
  efivars_exit(void)
  {
 -      if (efi_enabled) {
 +      if (efi_enabled(EFI_RUNTIME_SERVICES)) {
                unregister_efivars(&__efivars);
                kobject_put(efi_kobj);
        }