aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firmware/efivars.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index b605c4849772..d7658b4a5010 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -658,6 +658,7 @@ static ssize_t efivarfs_file_write(struct file *file,
658 u32 attributes; 658 u32 attributes;
659 struct inode *inode = file->f_mapping->host; 659 struct inode *inode = file->f_mapping->host;
660 int datasize = count - sizeof(attributes); 660 int datasize = count - sizeof(attributes);
661 unsigned long newdatasize;
661 662
662 if (count < sizeof(attributes)) 663 if (count < sizeof(attributes))
663 return -EINVAL; 664 return -EINVAL;
@@ -696,32 +697,60 @@ static ssize_t efivarfs_file_write(struct file *file,
696 697
697 switch (status) { 698 switch (status) {
698 case EFI_SUCCESS: 699 case EFI_SUCCESS:
699 mutex_lock(&inode->i_mutex);
700 i_size_write(inode, count);
701 mutex_unlock(&inode->i_mutex);
702 break; 700 break;
703 case EFI_INVALID_PARAMETER: 701 case EFI_INVALID_PARAMETER:
704 count = -EINVAL; 702 count = -EINVAL;
705 break; 703 goto out;
706 case EFI_OUT_OF_RESOURCES: 704 case EFI_OUT_OF_RESOURCES:
707 count = -ENOSPC; 705 count = -ENOSPC;
708 break; 706 goto out;
709 case EFI_DEVICE_ERROR: 707 case EFI_DEVICE_ERROR:
710 count = -EIO; 708 count = -EIO;
711 break; 709 goto out;
712 case EFI_WRITE_PROTECTED: 710 case EFI_WRITE_PROTECTED:
713 count = -EROFS; 711 count = -EROFS;
714 break; 712 goto out;
715 case EFI_SECURITY_VIOLATION: 713 case EFI_SECURITY_VIOLATION:
716 count = -EACCES; 714 count = -EACCES;
717 break; 715 goto out;
718 case EFI_NOT_FOUND: 716 case EFI_NOT_FOUND:
719 count = -ENOENT; 717 count = -ENOENT;
720 break; 718 goto out;
721 default: 719 default:
722 count = -EINVAL; 720 count = -EINVAL;
723 break; 721 goto out;
724 } 722 }
723
724 /*
725 * Writing to the variable may have caused a change in size (which
726 * could either be an append or an overwrite), or the variable to be
727 * deleted. Perform a GetVariable() so we can tell what actually
728 * happened.
729 */
730 newdatasize = 0;
731 status = efivars->ops->get_variable(var->var.VariableName,
732 &var->var.VendorGuid,
733 NULL, &newdatasize,
734 NULL);
735
736 if (status == EFI_BUFFER_TOO_SMALL) {
737 mutex_lock(&inode->i_mutex);
738 i_size_write(inode, newdatasize + sizeof(attributes));
739 mutex_unlock(&inode->i_mutex);
740
741 } else if (status == EFI_NOT_FOUND) {
742 spin_lock(&efivars->lock);
743 list_del(&var->list);
744 spin_unlock(&efivars->lock);
745 efivar_unregister(var);
746 drop_nlink(inode);
747 dput(file->f_dentry);
748
749 } else {
750 pr_warn("efivarfs: inconsistent EFI variable implementation? "
751 "status = %lx\n", status);
752 }
753
725out: 754out:
726 kfree(data); 755 kfree(data);
727 756