Merge remote-tracking branch 'efi/chainsaw' into x86/efi
authorH. Peter Anvin <hpa@linux.intel.com>
Sat, 20 Apr 2013 16:16:44 +0000 (09:16 -0700)
committerH. Peter Anvin <hpa@linux.intel.com>
Sat, 20 Apr 2013 16:16:44 +0000 (09:16 -0700)
Resolved Conflicts:
drivers/firmware/efivars.c
fs/efivarsfs/file.c

Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
1  2 
arch/x86/platform/efi/efi.c
fs/efivarfs/file.c

index 430cd784a0de8ea3e1886576e4605b761df4ab76,5f2ecaf3f9d8609ccdc7a56e4d232fd13bdd8dcc..fff986da623990cf74b649f5288f4c22df81ccf9
@@@ -80,9 -80,10 +80,10 @@@ int efi_enabled(int facility
  }
  EXPORT_SYMBOL(efi_enabled);
  
+ static bool __initdata disable_runtime = false;
  static int __init setup_noefi(char *arg)
  {
-       clear_bit(EFI_BOOT, &x86_efi_facility);
+       disable_runtime = true;
        return 0;
  }
  early_param("noefi", setup_noefi);
@@@ -350,25 -351,24 +351,25 @@@ static void __init do_add_efi_memmap(vo
  
  int __init efi_memblock_x86_reserve_range(void)
  {
 +      struct efi_info *e = &boot_params.efi_info;
        unsigned long pmap;
  
  #ifdef CONFIG_X86_32
        /* Can't handle data above 4GB at this time */
 -      if (boot_params.efi_info.efi_memmap_hi) {
 +      if (e->efi_memmap_hi) {
                pr_err("Memory map is above 4GB, disabling EFI.\n");
                return -EINVAL;
        }
 -      pmap = boot_params.efi_info.efi_memmap;
 +      pmap =  e->efi_memmap;
  #else
 -      pmap = (boot_params.efi_info.efi_memmap |
 -              ((__u64)boot_params.efi_info.efi_memmap_hi<<32));
 +      pmap = (e->efi_memmap | ((__u64)e->efi_memmap_hi << 32));
  #endif
 -      memmap.phys_map = (void *)pmap;
 -      memmap.nr_map = boot_params.efi_info.efi_memmap_size /
 -              boot_params.efi_info.efi_memdesc_size;
 -      memmap.desc_version = boot_params.efi_info.efi_memdesc_version;
 -      memmap.desc_size = boot_params.efi_info.efi_memdesc_size;
 +      memmap.phys_map         = (void *)pmap;
 +      memmap.nr_map           = e->efi_memmap_size /
 +                                e->efi_memdesc_size;
 +      memmap.desc_size        = e->efi_memdesc_size;
 +      memmap.desc_version     = e->efi_memdesc_version;
 +
        memblock_reserve(pmap, memmap.nr_map * memmap.desc_size);
  
        return 0;
@@@ -412,8 -412,8 +413,8 @@@ void __init efi_reserve_boot_services(v
                 * - Not within any part of the kernel
                 * - Not the bios reserved area
                */
-               if ((start+size >= virt_to_phys(_text)
-                               && start <= virt_to_phys(_end)) ||
+               if ((start+size >= __pa_symbol(_text)
+                               && start <= __pa_symbol(_end)) ||
                        !e820_all_mapped(start, start+size, E820_RAM) ||
                        memblock_is_region_reserved(start, size)) {
                        /* Could not reserve, skip it */
@@@ -730,7 -730,7 +731,7 @@@ void __init efi_init(void
        if (!efi_is_native())
                pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
        else {
-               if (efi_runtime_init())
+               if (disable_runtime || efi_runtime_init())
                        return;
                set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
        }
@@@ -839,7 -839,7 +840,7 @@@ void __init efi_enter_virtual_mode(void
        efi_memory_desc_t *md, *prev_md = NULL;
        efi_status_t status;
        unsigned long size;
-       u64 end, systab, end_pfn;
+       u64 end, systab, start_pfn, end_pfn;
        void *p, *va, *new_memmap = NULL;
        int count = 0;
  
                size = md->num_pages << EFI_PAGE_SHIFT;
                end = md->phys_addr + size;
  
+               start_pfn = PFN_DOWN(md->phys_addr);
                end_pfn = PFN_UP(end);
-               if (end_pfn <= max_low_pfn_mapped
-                   || (end_pfn > (1UL << (32 - PAGE_SHIFT))
-                       && end_pfn <= max_pfn_mapped)) {
+               if (pfn_range_is_mapped(start_pfn, end_pfn)) {
                        va = __va(md->phys_addr);
  
                        if (!(md->attribute & EFI_MEMORY_WB))
diff --combined fs/efivarfs/file.c
index 0000000000000000000000000000000000000000,aeb0368dace224e3edf69b89d9b26dffca3014d5..ede07fc7309f8b16ab0a69941d5391d394a27550
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,111 +1,105 @@@
 -static int efivarfs_file_open(struct inode *inode, struct file *file)
 -{
 -      file->private_data = inode->i_private;
 -      return 0;
 -}
 -
+ /*
+  * Copyright (C) 2012 Red Hat, Inc.
+  * Copyright (C) 2012 Jeremy Kerr <jeremy.kerr@canonical.com>
+  *
+  * This program is free software; you can redistribute it and/or modify
+  * it under the terms of the GNU General Public License version 2 as
+  * published by the Free Software Foundation.
+  */
+ #include <linux/efi.h>
+ #include <linux/fs.h>
+ #include "internal.h"
 -      .open   = efivarfs_file_open,
+ static ssize_t efivarfs_file_write(struct file *file,
+               const char __user *userbuf, size_t count, loff_t *ppos)
+ {
+       struct efivar_entry *var = file->private_data;
+       void *data;
+       u32 attributes;
+       struct inode *inode = file->f_mapping->host;
+       unsigned long datasize = count - sizeof(attributes);
+       ssize_t bytes = 0;
+       bool set = false;
+       if (count < sizeof(attributes))
+               return -EINVAL;
+       if (copy_from_user(&attributes, userbuf, sizeof(attributes)))
+               return -EFAULT;
+       if (attributes & ~(EFI_VARIABLE_MASK))
+               return -EINVAL;
+       data = kmalloc(datasize, GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       if (copy_from_user(data, userbuf + sizeof(attributes), datasize)) {
+               bytes = -EFAULT;
+               goto out;
+       }
+       bytes = efivar_entry_set_get_size(var, attributes, &datasize,
+                                         data, &set);
+       if (!set && bytes)
+               goto out;
+       if (bytes == -ENOENT) {
+               drop_nlink(inode);
+               d_delete(file->f_dentry);
+               dput(file->f_dentry);
+       } else {
+               mutex_lock(&inode->i_mutex);
+               i_size_write(inode, datasize + sizeof(attributes));
+               mutex_unlock(&inode->i_mutex);
+       }
+       bytes = count;
+ out:
+       kfree(data);
+       return bytes;
+ }
+ static ssize_t efivarfs_file_read(struct file *file, char __user *userbuf,
+               size_t count, loff_t *ppos)
+ {
+       struct efivar_entry *var = file->private_data;
+       unsigned long datasize = 0;
+       u32 attributes;
+       void *data;
+       ssize_t size = 0;
+       int err;
+       err = efivar_entry_size(var, &datasize);
+       if (err)
+               return err;
+       data = kmalloc(datasize + sizeof(attributes), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       size = efivar_entry_get(var, &attributes, &datasize,
+                               data + sizeof(attributes));
+       if (size)
+               goto out_free;
+       memcpy(data, &attributes, sizeof(attributes));
+       size = simple_read_from_buffer(userbuf, count, ppos,
+                                      data, datasize + sizeof(attributes));
+ out_free:
+       kfree(data);
+       return size;
+ }
+ const struct file_operations efivarfs_file_operations = {
++      .open   = simple_open,
+       .read   = efivarfs_file_read,
+       .write  = efivarfs_file_write,
+       .llseek = no_llseek,
+ };