diff options
Diffstat (limited to 'drivers/firmware/efi')
| -rw-r--r-- | drivers/firmware/efi/capsule-loader.c | 45 | ||||
| -rw-r--r-- | drivers/firmware/efi/efi.c | 5 | ||||
| -rw-r--r-- | drivers/firmware/efi/esrt.c | 17 | ||||
| -rw-r--r-- | drivers/firmware/efi/runtime-map.c | 10 | 
4 files changed, 52 insertions, 25 deletions
diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index ec8ac5c4dd84..055e2e8f985a 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c @@ -20,10 +20,6 @@  #define NO_FURTHER_WRITE_ACTION -1 -#ifndef phys_to_page -#define phys_to_page(x)		pfn_to_page((x) >> PAGE_SHIFT) -#endif -  /**   * efi_free_all_buff_pages - free all previous allocated buffer pages   * @cap_info: pointer to current instance of capsule_info structure @@ -35,7 +31,7 @@  static void efi_free_all_buff_pages(struct capsule_info *cap_info)  {  	while (cap_info->index > 0) -		__free_page(phys_to_page(cap_info->pages[--cap_info->index])); +		__free_page(cap_info->pages[--cap_info->index]);  	cap_info->index = NO_FURTHER_WRITE_ACTION;  } @@ -71,6 +67,14 @@ int __efi_capsule_setup_info(struct capsule_info *cap_info)  	cap_info->pages = temp_page; +	temp_page = krealloc(cap_info->phys, +			     pages_needed * sizeof(phys_addr_t *), +			     GFP_KERNEL | __GFP_ZERO); +	if (!temp_page) +		return -ENOMEM; + +	cap_info->phys = temp_page; +  	return 0;  } @@ -105,9 +109,24 @@ int __weak efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,   **/  static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info)  { +	bool do_vunmap = false;  	int ret; -	ret = efi_capsule_update(&cap_info->header, cap_info->pages); +	/* +	 * cap_info->capsule may have been assigned already by a quirk +	 * handler, so only overwrite it if it is NULL +	 */ +	if (!cap_info->capsule) { +		cap_info->capsule = vmap(cap_info->pages, cap_info->index, +					 VM_MAP, PAGE_KERNEL); +		if (!cap_info->capsule) +			return -ENOMEM; +		do_vunmap = true; +	} + +	ret = efi_capsule_update(cap_info->capsule, cap_info->phys); +	if (do_vunmap) +		vunmap(cap_info->capsule);  	if (ret) {  		pr_err("capsule update failed\n");  		return ret; @@ -165,10 +184,12 @@ static ssize_t efi_capsule_write(struct file *file, const char __user *buff,  			goto failed;  		} -		cap_info->pages[cap_info->index++] = page_to_phys(page); +		cap_info->pages[cap_info->index] = page; +		cap_info->phys[cap_info->index] = page_to_phys(page);  		cap_info->page_bytes_remain = PAGE_SIZE; +		cap_info->index++;  	} else { -		page = phys_to_page(cap_info->pages[cap_info->index - 1]); +		page = cap_info->pages[cap_info->index - 1];  	}  	kbuff = kmap(page); @@ -252,6 +273,7 @@ static int efi_capsule_release(struct inode *inode, struct file *file)  	struct capsule_info *cap_info = file->private_data;  	kfree(cap_info->pages); +	kfree(cap_info->phys);  	kfree(file->private_data);  	file->private_data = NULL;  	return 0; @@ -281,6 +303,13 @@ static int efi_capsule_open(struct inode *inode, struct file *file)  		return -ENOMEM;  	} +	cap_info->phys = kzalloc(sizeof(void *), GFP_KERNEL); +	if (!cap_info->phys) { +		kfree(cap_info->pages); +		kfree(cap_info); +		return -ENOMEM; +	} +  	file->private_data = cap_info;  	return 0; diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index f70febf680c3..557a47829d03 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -109,6 +109,8 @@ struct kobject *efi_kobj;  /*   * Let's not leave out systab information that snuck into   * the efivars driver + * Note, do not add more fields in systab sysfs file as it breaks sysfs + * one value per file rule!   */  static ssize_t systab_show(struct kobject *kobj,  			   struct kobj_attribute *attr, char *buf) @@ -143,8 +145,7 @@ static ssize_t systab_show(struct kobject *kobj,  	return str - buf;  } -static struct kobj_attribute efi_attr_systab = -			__ATTR(systab, 0400, systab_show, NULL); +static struct kobj_attribute efi_attr_systab = __ATTR_RO_MODE(systab, 0400);  #define EFI_FIELD(var) efi.var diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c index bd7ed3c1148a..c47e0c6ec00f 100644 --- a/drivers/firmware/efi/esrt.c +++ b/drivers/firmware/efi/esrt.c @@ -106,7 +106,7 @@ static const struct sysfs_ops esre_attr_ops = {  };  /* Generic ESRT Entry ("ESRE") support. */ -static ssize_t esre_fw_class_show(struct esre_entry *entry, char *buf) +static ssize_t fw_class_show(struct esre_entry *entry, char *buf)  {  	char *str = buf; @@ -117,18 +117,16 @@ static ssize_t esre_fw_class_show(struct esre_entry *entry, char *buf)  	return str - buf;  } -static struct esre_attribute esre_fw_class = __ATTR(fw_class, 0400, -	esre_fw_class_show, NULL); +static struct esre_attribute esre_fw_class = __ATTR_RO_MODE(fw_class, 0400);  #define esre_attr_decl(name, size, fmt) \ -static ssize_t esre_##name##_show(struct esre_entry *entry, char *buf) \ +static ssize_t name##_show(struct esre_entry *entry, char *buf) \  { \  	return sprintf(buf, fmt "\n", \  		       le##size##_to_cpu(entry->esre.esre1->name)); \  } \  \ -static struct esre_attribute esre_##name = __ATTR(name, 0400, \ -	esre_##name##_show, NULL) +static struct esre_attribute esre_##name = __ATTR_RO_MODE(name, 0400)  esre_attr_decl(fw_type, 32, "%u");  esre_attr_decl(fw_version, 32, "%u"); @@ -193,14 +191,13 @@ static int esre_create_sysfs_entry(void *esre, int entry_num)  /* support for displaying ESRT fields at the top level */  #define esrt_attr_decl(name, size, fmt) \ -static ssize_t esrt_##name##_show(struct kobject *kobj, \ +static ssize_t name##_show(struct kobject *kobj, \  				  struct kobj_attribute *attr, char *buf)\  { \  	return sprintf(buf, fmt "\n", le##size##_to_cpu(esrt->name)); \  } \  \ -static struct kobj_attribute esrt_##name = __ATTR(name, 0400, \ -	esrt_##name##_show, NULL) +static struct kobj_attribute esrt_##name = __ATTR_RO_MODE(name, 0400)  esrt_attr_decl(fw_resource_count, 32, "%u");  esrt_attr_decl(fw_resource_count_max, 32, "%u"); @@ -431,7 +428,7 @@ err_remove_group:  err_remove_esrt:  	kobject_put(esrt_kobj);  err: -	kfree(esrt); +	memunmap(esrt);  	esrt = NULL;  	return error;  } diff --git a/drivers/firmware/efi/runtime-map.c b/drivers/firmware/efi/runtime-map.c index 8e64b77aeac9..f377609ff141 100644 --- a/drivers/firmware/efi/runtime-map.c +++ b/drivers/firmware/efi/runtime-map.c @@ -63,11 +63,11 @@ static ssize_t map_attr_show(struct kobject *kobj, struct attribute *attr,  	return map_attr->show(entry, buf);  } -static struct map_attribute map_type_attr = __ATTR_RO(type); -static struct map_attribute map_phys_addr_attr   = __ATTR_RO(phys_addr); -static struct map_attribute map_virt_addr_attr  = __ATTR_RO(virt_addr); -static struct map_attribute map_num_pages_attr  = __ATTR_RO(num_pages); -static struct map_attribute map_attribute_attr  = __ATTR_RO(attribute); +static struct map_attribute map_type_attr = __ATTR_RO_MODE(type, 0400); +static struct map_attribute map_phys_addr_attr = __ATTR_RO_MODE(phys_addr, 0400); +static struct map_attribute map_virt_addr_attr = __ATTR_RO_MODE(virt_addr, 0400); +static struct map_attribute map_num_pages_attr = __ATTR_RO_MODE(num_pages, 0400); +static struct map_attribute map_attribute_attr = __ATTR_RO_MODE(attribute, 0400);  /*   * These are default attributes that are added for every memmap entry.  | 

