Patchwork [2/2] efi_runtime: add UEFI runtime service QueryVariableInfo interface

login
register
mail settings
Submitter Ivan Hu
Date Sept. 28, 2012, 8:26 a.m.
Message ID <1348820809-4489-1-git-send-email-ivan.hu@canonical.com>
Download mbox | patch
Permalink /patch/187733/
State Accepted
Headers show

Comments

Ivan Hu - Sept. 28, 2012, 8:26 a.m.
This interface is always returned EFI_UNSUPPORTED from
virt_fei_query_variable_info on kernel driver efi.c because of checking
the runtime_version. It seems that runtime_version value always 0,
it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.

Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
---
 efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
 efi_runtime/efi_runtime.h |   11 +++++++++++
 2 files changed, 31 insertions(+)
Keng-Yu Lin - Oct. 3, 2012, 8:10 a.m.
Hi Ivan,
  The commit log looks like a bug in the kernel you found while you
were implementing this patch.
  Do you have further analysis or idea on the cause or how it can be
potentially fixed we can probably help out here?

On Fri, Sep 28, 2012 at 4:26 PM, Ivan Hu <ivan.hu@canonical.com> wrote:
> This interface is always returned EFI_UNSUPPORTED from
> virt_fei_query_variable_info on kernel driver efi.c because of checking
> the runtime_version. It seems that runtime_version value always 0,
> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.
>
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>  efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>  efi_runtime/efi_runtime.h |   11 +++++++++++
>  2 files changed, 31 insertions(+)
>
> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
> index 227a910..0e66e94 100644
> --- a/efi_runtime/efi_runtime.c
> +++ b/efi_runtime/efi_runtime.c
> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>         struct efi_getnextvariablename __user *pgetnextvariablename;
>         unsigned long name_size;
>
> +       struct efi_queryvariableinfo __user *pqueryvariableinfo;
> +
>         switch (cmd) {
>         case EFI_RUNTIME_GET_VARIABLE:
>                 pgetvariable = (struct efi_getvariable __user *)arg;
> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>                                                 &vendor_guid, sizeof(EFI_GUID)))
>                         return -EFAULT;
>                 return 0;
> +
> +       case EFI_RUNTIME_QUERY_VARIABLEINFO:
> +
> +               pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
> +
> +               if (get_user(attr, &pqueryvariableinfo->Attributes))
> +                       return -EFAULT;
> +
> +               status = efi.query_variable_info(attr,
> +                               pqueryvariableinfo->MaximumVariableStorageSize,
> +                               pqueryvariableinfo->RemainingVariableStorageSize
> +                               , pqueryvariableinfo->MaximumVariableSize);
> +               if (put_user(status, pqueryvariableinfo->status))
> +                       return -EFAULT;
> +               if (status != EFI_SUCCESS)
> +                       return -EINVAL;
> +
> +               return 0;
>         }
>
>         return -ENOTTY;
> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
> index 7387406..cc33878 100644
> --- a/efi_runtime/efi_runtime.h
> +++ b/efi_runtime/efi_runtime.h
> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>         uint64_t        *status;
>  } __attribute__ ((packed));
>
> +struct efi_queryvariableinfo {
> +       uint32_t        Attributes;
> +       uint64_t        *MaximumVariableStorageSize;
> +       uint64_t        *RemainingVariableStorageSize;
> +       uint64_t        *MaximumVariableSize;
> +       uint64_t        *status;
> +} __attribute__ ((packed));
> +
>  struct efi_gettime {
>         EFI_TIME                *Time;
>         EFI_TIME_CAPABILITIES   *Capabilities;
> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>  #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>         _IOWR('p', 0x07, struct efi_getnextvariablename)
>
> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
> +       _IOR('p', 0x08, struct efi_queryvariableinfo)
> +
>  #endif /* _EFI_RUNTIME_H_ */
> --
> 1.7.9.5
>
>
> --
> fwts-devel mailing list
> fwts-devel@lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/fwts-devel
Ivan Hu - Oct. 3, 2012, 9:33 a.m.
Hi Kengyu,

This interface will call the RT service via virt_efi_query_variable_info 
function in efi.c below:

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);
}

I dumped the value runtime_version equal 0 and it seems that the value 
of runtime_version doesn't be set. I think the kernel may not implement 
to check the version. I did a simple test as well, just removed the 
checking runtime version, directly call the efi_call_virt4, the function 
worked fine.

On 10/03/2012 04:10 PM, Keng-Yu Lin wrote:
> Hi Ivan,
>    The commit log looks like a bug in the kernel you found while you
> were implementing this patch.
>    Do you have further analysis or idea on the cause or how it can be
> potentially fixed we can probably help out here?
>
> On Fri, Sep 28, 2012 at 4:26 PM, Ivan Hu <ivan.hu@canonical.com> wrote:
>> This interface is always returned EFI_UNSUPPORTED from
>> virt_fei_query_variable_info on kernel driver efi.c because of checking
>> the runtime_version. It seems that runtime_version value always 0,
>> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.
>>
>> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
>> ---
>>   efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>>   efi_runtime/efi_runtime.h |   11 +++++++++++
>>   2 files changed, 31 insertions(+)
>>
>> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
>> index 227a910..0e66e94 100644
>> --- a/efi_runtime/efi_runtime.c
>> +++ b/efi_runtime/efi_runtime.c
>> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>>          struct efi_getnextvariablename __user *pgetnextvariablename;
>>          unsigned long name_size;
>>
>> +       struct efi_queryvariableinfo __user *pqueryvariableinfo;
>> +
>>          switch (cmd) {
>>          case EFI_RUNTIME_GET_VARIABLE:
>>                  pgetvariable = (struct efi_getvariable __user *)arg;
>> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>>                                                  &vendor_guid, sizeof(EFI_GUID)))
>>                          return -EFAULT;
>>                  return 0;
>> +
>> +       case EFI_RUNTIME_QUERY_VARIABLEINFO:
>> +
>> +               pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
>> +
>> +               if (get_user(attr, &pqueryvariableinfo->Attributes))
>> +                       return -EFAULT;
>> +
>> +               status = efi.query_variable_info(attr,
>> +                               pqueryvariableinfo->MaximumVariableStorageSize,
>> +                               pqueryvariableinfo->RemainingVariableStorageSize
>> +                               , pqueryvariableinfo->MaximumVariableSize);
>> +               if (put_user(status, pqueryvariableinfo->status))
>> +                       return -EFAULT;
>> +               if (status != EFI_SUCCESS)
>> +                       return -EINVAL;
>> +
>> +               return 0;
>>          }
>>
>>          return -ENOTTY;
>> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
>> index 7387406..cc33878 100644
>> --- a/efi_runtime/efi_runtime.h
>> +++ b/efi_runtime/efi_runtime.h
>> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>>          uint64_t        *status;
>>   } __attribute__ ((packed));
>>
>> +struct efi_queryvariableinfo {
>> +       uint32_t        Attributes;
>> +       uint64_t        *MaximumVariableStorageSize;
>> +       uint64_t        *RemainingVariableStorageSize;
>> +       uint64_t        *MaximumVariableSize;
>> +       uint64_t        *status;
>> +} __attribute__ ((packed));
>> +
>>   struct efi_gettime {
>>          EFI_TIME                *Time;
>>          EFI_TIME_CAPABILITIES   *Capabilities;
>> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>>   #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>>          _IOWR('p', 0x07, struct efi_getnextvariablename)
>>
>> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
>> +       _IOR('p', 0x08, struct efi_queryvariableinfo)
>> +
>>   #endif /* _EFI_RUNTIME_H_ */
>> --
>> 1.7.9.5
>>
>>
>> --
>> fwts-devel mailing list
>> fwts-devel@lists.ubuntu.com
>> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/fwts-devel
>
Keng-Yu Lin - Oct. 3, 2012, 10:03 a.m.
From the same file in static int __init efi_systab_init(void *phys)

                systab64 = early_ioremap((unsigned long)phys,
                                         sizeof(*systab64));
                ...(skip)...
                efi_systab.fw_revision = systab64->fw_revision;

And later
                efi.runtime_version = efi_systab.fw_revision;

I think the error you met is just the kernel checking result. (we can
probably check other machines).

Thanks for the information, this helps the review.

On Wed, Oct 3, 2012 at 5:33 PM, IvanHu <ivan.hu@canonical.com> wrote:
> Hi Kengyu,
>
> This interface will call the RT service via virt_efi_query_variable_info
> function in efi.c below:
>
> 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);
> }
>
> I dumped the value runtime_version equal 0 and it seems that the value of
> runtime_version doesn't be set. I think the kernel may not implement to
> check the version. I did a simple test as well, just removed the checking
> runtime version, directly call the efi_call_virt4, the function worked fine.
>
>
> On 10/03/2012 04:10 PM, Keng-Yu Lin wrote:
>>
>> Hi Ivan,
>>    The commit log looks like a bug in the kernel you found while you
>> were implementing this patch.
>>    Do you have further analysis or idea on the cause or how it can be
>> potentially fixed we can probably help out here?
>>
>> On Fri, Sep 28, 2012 at 4:26 PM, Ivan Hu <ivan.hu@canonical.com> wrote:
>>>
>>> This interface is always returned EFI_UNSUPPORTED from
>>> virt_fei_query_variable_info on kernel driver efi.c because of checking
>>> the runtime_version. It seems that runtime_version value always 0,
>>> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this
>>> interface.
>>>
>>> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
>>> ---
>>>   efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>>>   efi_runtime/efi_runtime.h |   11 +++++++++++
>>>   2 files changed, 31 insertions(+)
>>>
>>> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
>>> index 227a910..0e66e94 100644
>>> --- a/efi_runtime/efi_runtime.c
>>> +++ b/efi_runtime/efi_runtime.c
>>> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file,
>>> unsigned int cmd,
>>>          struct efi_getnextvariablename __user *pgetnextvariablename;
>>>          unsigned long name_size;
>>>
>>> +       struct efi_queryvariableinfo __user *pqueryvariableinfo;
>>> +
>>>          switch (cmd) {
>>>          case EFI_RUNTIME_GET_VARIABLE:
>>>                  pgetvariable = (struct efi_getvariable __user *)arg;
>>> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file,
>>> unsigned int cmd,
>>>                                                  &vendor_guid,
>>> sizeof(EFI_GUID)))
>>>                          return -EFAULT;
>>>                  return 0;
>>> +
>>> +       case EFI_RUNTIME_QUERY_VARIABLEINFO:
>>> +
>>> +               pqueryvariableinfo = (struct efi_queryvariableinfo __user
>>> *)arg;
>>> +
>>> +               if (get_user(attr, &pqueryvariableinfo->Attributes))
>>> +                       return -EFAULT;
>>> +
>>> +               status = efi.query_variable_info(attr,
>>> +
>>> pqueryvariableinfo->MaximumVariableStorageSize,
>>> +
>>> pqueryvariableinfo->RemainingVariableStorageSize
>>> +                               ,
>>> pqueryvariableinfo->MaximumVariableSize);
>>> +               if (put_user(status, pqueryvariableinfo->status))
>>> +                       return -EFAULT;
>>> +               if (status != EFI_SUCCESS)
>>> +                       return -EINVAL;
>>> +
>>> +               return 0;
>>>          }
>>>
>>>          return -ENOTTY;
>>> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
>>> index 7387406..cc33878 100644
>>> --- a/efi_runtime/efi_runtime.h
>>> +++ b/efi_runtime/efi_runtime.h
>>> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>>>          uint64_t        *status;
>>>   } __attribute__ ((packed));
>>>
>>> +struct efi_queryvariableinfo {
>>> +       uint32_t        Attributes;
>>> +       uint64_t        *MaximumVariableStorageSize;
>>> +       uint64_t        *RemainingVariableStorageSize;
>>> +       uint64_t        *MaximumVariableSize;
>>> +       uint64_t        *status;
>>> +} __attribute__ ((packed));
>>> +
>>>   struct efi_gettime {
>>>          EFI_TIME                *Time;
>>>          EFI_TIME_CAPABILITIES   *Capabilities;
>>> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>>>   #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>>>          _IOWR('p', 0x07, struct efi_getnextvariablename)
>>>
>>> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
>>> +       _IOR('p', 0x08, struct efi_queryvariableinfo)
>>> +
>>>   #endif /* _EFI_RUNTIME_H_ */
>>> --
>>> 1.7.9.5
>>>
>>>
>>> --
>>> fwts-devel mailing list
>>> fwts-devel@lists.ubuntu.com
>>> Modify settings or unsubscribe at:
>>> https://lists.ubuntu.com/mailman/listinfo/fwts-devel
>>
>>
>
Ivan Hu - Oct. 9, 2012, 7:02 a.m.
yup, the patch upstream to kernel could solve this problem.

commit d6cf86d8f23253225fe2a763d627ecf7dfee9dae
efi: initialize efi.runtime_version to make 
query_variable_info/update_capsule workable

This patch should work on version 3.6, but not on the Quantal.
I also upstream to stable tree of kernel version 3.5. Hope it could be 
workable earlier.
Keng-Yu Lin - Oct. 9, 2012, 7:14 a.m.
On Tue, Oct 9, 2012 at 3:02 PM, IvanHu <ivan.hu@canonical.com> wrote:
> yup, the patch upstream to kernel could solve this problem.
>
> commit d6cf86d8f23253225fe2a763d627ecf7dfee9dae
> efi: initialize efi.runtime_version to make
> query_variable_info/update_capsule workable
>
> This patch should work on version 3.6, but not on the Quantal.
> I also upstream to stable tree of kernel version 3.5. Hope it could be
> workable earlier.

Thanks Ivan for getting this into the 3.5.y -stable.
Keng-Yu Lin - Oct. 16, 2012, 9:31 a.m.
On Fri, Sep 28, 2012 at 4:26 PM, Ivan Hu <ivan.hu@canonical.com> wrote:
> This interface is always returned EFI_UNSUPPORTED from
> virt_fei_query_variable_info on kernel driver efi.c because of checking
> the runtime_version. It seems that runtime_version value always 0,
> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.
>
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>  efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>  efi_runtime/efi_runtime.h |   11 +++++++++++
>  2 files changed, 31 insertions(+)
>
> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
> index 227a910..0e66e94 100644
> --- a/efi_runtime/efi_runtime.c
> +++ b/efi_runtime/efi_runtime.c
> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>         struct efi_getnextvariablename __user *pgetnextvariablename;
>         unsigned long name_size;
>
> +       struct efi_queryvariableinfo __user *pqueryvariableinfo;
> +
>         switch (cmd) {
>         case EFI_RUNTIME_GET_VARIABLE:
>                 pgetvariable = (struct efi_getvariable __user *)arg;
> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>                                                 &vendor_guid, sizeof(EFI_GUID)))
>                         return -EFAULT;
>                 return 0;
> +
> +       case EFI_RUNTIME_QUERY_VARIABLEINFO:
> +
> +               pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
> +
> +               if (get_user(attr, &pqueryvariableinfo->Attributes))
> +                       return -EFAULT;
> +
> +               status = efi.query_variable_info(attr,
> +                               pqueryvariableinfo->MaximumVariableStorageSize,
> +                               pqueryvariableinfo->RemainingVariableStorageSize
> +                               , pqueryvariableinfo->MaximumVariableSize);
> +               if (put_user(status, pqueryvariableinfo->status))
> +                       return -EFAULT;
> +               if (status != EFI_SUCCESS)
> +                       return -EINVAL;
> +
> +               return 0;
>         }
>
>         return -ENOTTY;
> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
> index 7387406..cc33878 100644
> --- a/efi_runtime/efi_runtime.h
> +++ b/efi_runtime/efi_runtime.h
> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>         uint64_t        *status;
>  } __attribute__ ((packed));
>
> +struct efi_queryvariableinfo {
> +       uint32_t        Attributes;
> +       uint64_t        *MaximumVariableStorageSize;
> +       uint64_t        *RemainingVariableStorageSize;
> +       uint64_t        *MaximumVariableSize;
> +       uint64_t        *status;
> +} __attribute__ ((packed));
> +
>  struct efi_gettime {
>         EFI_TIME                *Time;
>         EFI_TIME_CAPABILITIES   *Capabilities;
> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>  #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>         _IOWR('p', 0x07, struct efi_getnextvariablename)
>
> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
> +       _IOR('p', 0x08, struct efi_queryvariableinfo)
> +
>  #endif /* _EFI_RUNTIME_H_ */
> --
> 1.7.9.5
>

Acked-by: Keng-Yu Lin <kengyu@canonical.com>
Alex Hung - Oct. 17, 2012, 2:44 p.m.
On 09/28/2012 04:26 PM, Ivan Hu wrote:
> This interface is always returned EFI_UNSUPPORTED from
> virt_fei_query_variable_info on kernel driver efi.c because of checking
> the runtime_version. It seems that runtime_version value always 0,
> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.
>
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>   efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>   efi_runtime/efi_runtime.h |   11 +++++++++++
>   2 files changed, 31 insertions(+)
>
> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
> index 227a910..0e66e94 100644
> --- a/efi_runtime/efi_runtime.c
> +++ b/efi_runtime/efi_runtime.c
> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>   	struct efi_getnextvariablename __user *pgetnextvariablename;
>   	unsigned long name_size;
>
> +	struct efi_queryvariableinfo __user *pqueryvariableinfo;
> +
>   	switch (cmd) {
>   	case EFI_RUNTIME_GET_VARIABLE:
>   		pgetvariable = (struct efi_getvariable __user *)arg;
> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>   						&vendor_guid, sizeof(EFI_GUID)))
>   			return -EFAULT;
>   		return 0;
> +
> +	case EFI_RUNTIME_QUERY_VARIABLEINFO:
> +
> +		pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
> +
> +		if (get_user(attr, &pqueryvariableinfo->Attributes))
> +			return -EFAULT;
> +
> +		status = efi.query_variable_info(attr,
> +				pqueryvariableinfo->MaximumVariableStorageSize,
> +				pqueryvariableinfo->RemainingVariableStorageSize
> +				, pqueryvariableinfo->MaximumVariableSize);
> +		if (put_user(status, pqueryvariableinfo->status))
> +			return -EFAULT;
> +		if (status != EFI_SUCCESS)
> +			return -EINVAL;
> +
> +		return 0;
>   	}
>
>   	return -ENOTTY;
> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
> index 7387406..cc33878 100644
> --- a/efi_runtime/efi_runtime.h
> +++ b/efi_runtime/efi_runtime.h
> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>   	uint64_t	*status;
>   } __attribute__ ((packed));
>
> +struct efi_queryvariableinfo {
> +	uint32_t	Attributes;
> +	uint64_t	*MaximumVariableStorageSize;
> +	uint64_t	*RemainingVariableStorageSize;
> +	uint64_t	*MaximumVariableSize;
> +	uint64_t	*status;
> +} __attribute__ ((packed));
> +
>   struct efi_gettime {
>   	EFI_TIME		*Time;
>   	EFI_TIME_CAPABILITIES	*Capabilities;
> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>   #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>   	_IOWR('p', 0x07, struct efi_getnextvariablename)
>
> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
> +	_IOR('p', 0x08, struct efi_queryvariableinfo)
> +
>   #endif /* _EFI_RUNTIME_H_ */
>

Acked-by: Alex Hung <alex.hung@canonical.com>
Colin King - Oct. 17, 2012, 2:54 p.m.
On 28/09/12 09:26, Ivan Hu wrote:
> This interface is always returned EFI_UNSUPPORTED from
> virt_fei_query_variable_info on kernel driver efi.c because of checking
> the runtime_version. It seems that runtime_version value always 0,
> it alway returns EFI_UNSUPPORTED. Need a patch of efi.c for this interface.
>
> Signed-off-by: Ivan Hu <ivan.hu@canonical.com>
> ---
>   efi_runtime/efi_runtime.c |   20 ++++++++++++++++++++
>   efi_runtime/efi_runtime.h |   11 +++++++++++
>   2 files changed, 31 insertions(+)
>
> diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
> index 227a910..0e66e94 100644
> --- a/efi_runtime/efi_runtime.c
> +++ b/efi_runtime/efi_runtime.c
> @@ -117,6 +117,8 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>   	struct efi_getnextvariablename __user *pgetnextvariablename;
>   	unsigned long name_size;
>
> +	struct efi_queryvariableinfo __user *pqueryvariableinfo;
> +
>   	switch (cmd) {
>   	case EFI_RUNTIME_GET_VARIABLE:
>   		pgetvariable = (struct efi_getvariable __user *)arg;
> @@ -261,6 +263,24 @@ static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
>   						&vendor_guid, sizeof(EFI_GUID)))
>   			return -EFAULT;
>   		return 0;
> +
> +	case EFI_RUNTIME_QUERY_VARIABLEINFO:
> +
> +		pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
> +
> +		if (get_user(attr, &pqueryvariableinfo->Attributes))
> +			return -EFAULT;
> +
> +		status = efi.query_variable_info(attr,
> +				pqueryvariableinfo->MaximumVariableStorageSize,
> +				pqueryvariableinfo->RemainingVariableStorageSize
> +				, pqueryvariableinfo->MaximumVariableSize);

Minor formatting issue          ^  comma should be end of previous line 
if possible.

> +		if (put_user(status, pqueryvariableinfo->status))
> +			return -EFAULT;
> +		if (status != EFI_SUCCESS)
> +			return -EINVAL;
> +
> +		return 0;
>   	}
>
>   	return -ENOTTY;
> diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
> index 7387406..cc33878 100644
> --- a/efi_runtime/efi_runtime.h
> +++ b/efi_runtime/efi_runtime.h
> @@ -73,6 +73,14 @@ struct efi_getnextvariablename {
>   	uint64_t	*status;
>   } __attribute__ ((packed));
>
> +struct efi_queryvariableinfo {
> +	uint32_t	Attributes;
> +	uint64_t	*MaximumVariableStorageSize;
> +	uint64_t	*RemainingVariableStorageSize;
> +	uint64_t	*MaximumVariableSize;
> +	uint64_t	*status;
> +} __attribute__ ((packed));
> +
>   struct efi_gettime {
>   	EFI_TIME		*Time;
>   	EFI_TIME_CAPABILITIES	*Capabilities;
> @@ -116,4 +124,7 @@ struct efi_setwakeuptime {
>   #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
>   	_IOWR('p', 0x07, struct efi_getnextvariablename)
>
> +#define EFI_RUNTIME_QUERY_VARIABLEINFO \
> +	_IOR('p', 0x08, struct efi_queryvariableinfo)
> +
>   #endif /* _EFI_RUNTIME_H_ */
>

Patch

diff --git a/efi_runtime/efi_runtime.c b/efi_runtime/efi_runtime.c
index 227a910..0e66e94 100644
--- a/efi_runtime/efi_runtime.c
+++ b/efi_runtime/efi_runtime.c
@@ -117,6 +117,8 @@  static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
 	struct efi_getnextvariablename __user *pgetnextvariablename;
 	unsigned long name_size;
 
+	struct efi_queryvariableinfo __user *pqueryvariableinfo;
+
 	switch (cmd) {
 	case EFI_RUNTIME_GET_VARIABLE:
 		pgetvariable = (struct efi_getvariable __user *)arg;
@@ -261,6 +263,24 @@  static long efi_runtime_ioctl(struct file *file, unsigned int cmd,
 						&vendor_guid, sizeof(EFI_GUID)))
 			return -EFAULT;
 		return 0;
+
+	case EFI_RUNTIME_QUERY_VARIABLEINFO:
+
+		pqueryvariableinfo = (struct efi_queryvariableinfo __user *)arg;
+
+		if (get_user(attr, &pqueryvariableinfo->Attributes))
+			return -EFAULT;
+
+		status = efi.query_variable_info(attr,
+				pqueryvariableinfo->MaximumVariableStorageSize,
+				pqueryvariableinfo->RemainingVariableStorageSize
+				, pqueryvariableinfo->MaximumVariableSize);
+		if (put_user(status, pqueryvariableinfo->status))
+			return -EFAULT;
+		if (status != EFI_SUCCESS)
+			return -EINVAL;
+
+		return 0;
 	}
 
 	return -ENOTTY;
diff --git a/efi_runtime/efi_runtime.h b/efi_runtime/efi_runtime.h
index 7387406..cc33878 100644
--- a/efi_runtime/efi_runtime.h
+++ b/efi_runtime/efi_runtime.h
@@ -73,6 +73,14 @@  struct efi_getnextvariablename {
 	uint64_t	*status;
 } __attribute__ ((packed));
 
+struct efi_queryvariableinfo {
+	uint32_t	Attributes;
+	uint64_t	*MaximumVariableStorageSize;
+	uint64_t	*RemainingVariableStorageSize;
+	uint64_t	*MaximumVariableSize;
+	uint64_t	*status;
+} __attribute__ ((packed));
+
 struct efi_gettime {
 	EFI_TIME		*Time;
 	EFI_TIME_CAPABILITIES	*Capabilities;
@@ -116,4 +124,7 @@  struct efi_setwakeuptime {
 #define EFI_RUNTIME_GET_NEXTVARIABLENAME \
 	_IOWR('p', 0x07, struct efi_getnextvariablename)
 
+#define EFI_RUNTIME_QUERY_VARIABLEINFO \
+	_IOR('p', 0x08, struct efi_queryvariableinfo)
+
 #endif /* _EFI_RUNTIME_H_ */