linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] firmware/efi: export a routine to retrieve efi-variables by GUID
@ 2011-03-18 22:16 Dan Williams
  2011-03-18 22:50 ` Greg KH
  2011-03-22  3:49 ` Matt Domsch
  0 siblings, 2 replies; 11+ messages in thread
From: Dan Williams @ 2011-03-18 22:16 UTC (permalink / raw)
  To: gregkh
  Cc: Dave Jiang, linux-scsi, jacek.danecki, ed.ciechanowski,
	linux-kernel, dmilburn, edmund.nadolski

From: Dave Jiang <dave.jiang@intel.com>

The efivars module already scans all available variables, normalizes the
variable names, and stores them in a list.  Rather than duplicate this
to efi runtime services interface let drivers query variable data by
GUID.

This is needed by the isci driver which relies on an efi variable to
store critical platform parameters like gloablly unique sas addresses
and phy configuration parameters.  This is similar to the
pci_map_biosrom() enabling that allows the isci driver to retrieve the
same data in the non-efi case.

For the built-in case efivars is moved to subsys_initcall.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
Not sure who looks after efivars.c, but get_maintainer.pl and git shortlog
fingered Greg as a likely target.

We are currently targeting a late merge of the isci driver through the
staging tree into 2.6.39.  This is a pre-requisite to be able to use the
driver on an efi enabled platform.

--
Dan

 drivers/firmware/efivars.c |   59 ++++++++++++++++++++++++++++++--------------
 include/linux/efi.h        |   22 ++++++++++++++++
 2 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 2a62ec6..e139dac 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -100,23 +100,6 @@ MODULE_VERSION(EFIVARS_VERSION);
 static DEFINE_SPINLOCK(efivars_lock);
 static LIST_HEAD(efivar_list);
 
-/*
- * The maximum size of VariableName + Data = 1024
- * Therefore, it's reasonable to save that much
- * space in each part of the structure,
- * and we use a page for reading/writing.
- */
-
-struct efi_variable {
-	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
-	efi_guid_t    VendorGuid;
-	unsigned long DataSize;
-	__u8          Data[1024];
-	efi_status_t  Status;
-	__u32         Attributes;
-} __attribute__((packed));
-
-
 struct efivar_entry {
 	struct efi_variable var;
 	struct list_head list;
@@ -169,6 +152,45 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength)
 	return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
 }
 
+efi_status_t
+efivar_get_data_from_guid(struct efi_variable *evar)
+{
+	struct efivar_entry *search_efivar;
+	unsigned long strsize;
+	efi_status_t status;
+	int found = 0;
+
+	spin_lock(&efivars_lock);
+
+	/* make sure this EFI variable is there */
+	list_for_each_entry(search_efivar, &efivar_list, list) {
+		if (!efi_guidcmp(search_efivar->var.VendorGuid,
+				 evar->VendorGuid)) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found) {
+		spin_unlock(&efivars_lock);
+		return EFI_NOT_FOUND;
+	}
+
+	strsize = utf8_strsize(search_efivar->var.VariableName, 1024);
+	memcpy(evar->VariableName, search_efivar->var.VariableName, strsize);
+
+	evar->DataSize = 1024;
+	status = efi.get_variable(evar->VariableName,
+				  &evar->VendorGuid,
+				  &evar->Attributes,
+				  &evar->DataSize,
+				  evar->Data);
+	spin_unlock(&efivars_lock);
+
+	return status;
+}
+EXPORT_SYMBOL(efivar_get_data_from_guid);
+
 static efi_status_t
 get_var_data(struct efi_variable *var)
 {
@@ -757,6 +779,5 @@ efivars_exit(void)
 	kobject_put(efi_kobj);
 }
 
-module_init(efivars_init);
+subsys_initcall(efivars_init);
 module_exit(efivars_exit);
-
diff --git a/include/linux/efi.h b/include/linux/efi.h
index fb737bc..4230bc5 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -243,6 +243,19 @@ struct efi_memory_map {
 	unsigned long desc_size;
 };
 
+/* The maximum size of VariableName + Data = 1024 Therefore, it's
+ * reasonable to save that much space in each part of the structure, and
+ * we use a page for reading/writing.
+ */
+struct efi_variable {
+	efi_char16_t  VariableName[1024/sizeof(efi_char16_t)];
+	efi_guid_t    VendorGuid;
+	unsigned long DataSize;
+	__u8          Data[1024];
+	efi_status_t  Status;
+	__u32         Attributes;
+} __attribute__((packed));
+
 #define EFI_INVALID_TABLE_ADDR		(~0UL)
 
 /*
@@ -326,6 +339,15 @@ static inline int efi_range_is_wc(unsigned long start, unsigned long len)
 extern int __init efi_setup_pcdp_console(char *);
 #endif
 
+#if defined(CONFIG_EFI_VARS) || defined(CONFIG_EFI_VARS_MODULE)
+extern efi_status_t efivar_get_data_from_guid(struct efi_variable *evar);
+#else
+static inline efi_status_t efivar_get_data_from_guid(struct efi_variable *evar)
+{
+	return EFI_NOT_FOUND;
+}
+#endif
+
 /*
  * We play games with efi_enabled so that the compiler will, if possible, remove
  * EFI-related code altogether.


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-03-22  3:49 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-18 22:16 [PATCH] firmware/efi: export a routine to retrieve efi-variables by GUID Dan Williams
2011-03-18 22:50 ` Greg KH
2011-03-18 23:10   ` Dan Williams
2011-03-19  0:22     ` Greg KH
2011-03-19  1:15       ` Dan Williams
2011-03-20  0:14         ` Greg KH
2011-03-20  1:13           ` James Bottomley
2011-03-21 19:07             ` Dan Williams
2011-03-21 19:12               ` Christoph Hellwig
2011-03-21 18:41           ` Dan Williams
2011-03-22  3:49 ` Matt Domsch

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).