* Add efi variables as a pstore backend
@ 2011-07-21 20:57 Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 1/9] pstore: Extend API Matthew Garrett
` (9 more replies)
0 siblings, 10 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck
The same as the last attempt, but with Tony's comments on patch 4 addressed.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 1/9] pstore: Extend API
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 2/9] pstore: Add extra context for writes and erases Matthew Garrett
` (8 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett
Some pstore implementations may not have a static context, so extend the
API to pass the pstore_info struct to all calls and allow for a context
pointer.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/acpi/apei/erst.c | 18 +++++++++++++-----
fs/pstore/inode.c | 10 +++++-----
fs/pstore/internal.h | 2 +-
fs/pstore/platform.c | 13 +++++++------
include/linux/pstore.h | 8 +++++---
5 files changed, 31 insertions(+), 20 deletions(-)
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index c8ba9da..8aac55e 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -932,8 +932,10 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
static int erst_open_pstore(struct pstore_info *psi);
static int erst_close_pstore(struct pstore_info *psi);
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
- struct timespec *time);
-static u64 erst_writer(enum pstore_type_id type, size_t size);
+ struct timespec *time, struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, size_t size,
+ struct pstore_info *psi);
+static int erst_clearer(u64 id, struct pstore_info *psi);
static struct pstore_info erst_info = {
.owner = THIS_MODULE,
@@ -942,7 +944,7 @@ static struct pstore_info erst_info = {
.close = erst_close_pstore,
.read = erst_reader,
.write = erst_writer,
- .erase = erst_clear
+ .erase = erst_clearer
};
#define CPER_CREATOR_PSTORE \
@@ -983,7 +985,7 @@ static int erst_close_pstore(struct pstore_info *psi)
}
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
- struct timespec *time)
+ struct timespec *time, struct pstore_info *psi)
{
int rc;
ssize_t len = 0;
@@ -1037,7 +1039,8 @@ out:
return (rc < 0) ? rc : (len - sizeof(*rcd));
}
-static u64 erst_writer(enum pstore_type_id type, size_t size)
+static u64 erst_writer(enum pstore_type_id type, size_t size,
+ struct pstore_info *psi)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));
@@ -1080,6 +1083,11 @@ static u64 erst_writer(enum pstore_type_id type, size_t size)
return rcd->hdr.record_id;
}
+static int erst_clearer(u64 id, struct pstore_info *psi)
+{
+ return erst_clear(id);
+}
+
static int __init erst_init(void)
{
int rc = 0;
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index 977ed27..b19884a 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -40,7 +40,7 @@
struct pstore_private {
u64 id;
- int (*erase)(u64);
+ struct pstore_info *psi;
ssize_t size;
char data[];
};
@@ -73,7 +73,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
{
struct pstore_private *p = dentry->d_inode->i_private;
- p->erase(p->id);
+ p->psi->erase(p->id, p->psi);
return simple_unlink(dir, dentry);
}
@@ -175,8 +175,8 @@ int pstore_is_mounted(void)
* Set the mtime & ctime to the date that this record was originally stored.
*/
int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
- char *data, size_t size,
- struct timespec time, int (*erase)(u64))
+ char *data, size_t size, struct timespec time,
+ struct pstore_info *psi)
{
struct dentry *root = pstore_sb->s_root;
struct dentry *dentry;
@@ -193,7 +193,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
if (!private)
goto fail_alloc;
private->id = id;
- private->erase = erase;
+ private->psi = psi;
switch (type) {
case PSTORE_TYPE_DMESG:
diff --git a/fs/pstore/internal.h b/fs/pstore/internal.h
index 8c9f23e..611c1b3 100644
--- a/fs/pstore/internal.h
+++ b/fs/pstore/internal.h
@@ -2,5 +2,5 @@ extern void pstore_set_kmsg_bytes(int);
extern void pstore_get_records(void);
extern int pstore_mkfile(enum pstore_type_id, char *psname, u64 id,
char *data, size_t size,
- struct timespec time, int (*erase)(u64));
+ struct timespec time, struct pstore_info *psi);
extern int pstore_is_mounted(void);
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index f2c3ff2..221c04e 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -94,11 +94,12 @@ static void pstore_dump(struct kmsg_dumper *dumper,
memcpy(dst, s1 + s1_start, l1_cpy);
memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
- id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
+ id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy,
+ psinfo);
if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
psinfo->buf, hsize + l1_cpy + l2_cpy,
- CURRENT_TIME, psinfo->erase);
+ CURRENT_TIME, psinfo);
l1 -= l1_cpy;
l2 -= l2_cpy;
total += l1_cpy + l2_cpy;
@@ -166,9 +167,9 @@ void pstore_get_records(void)
if (rc)
goto out;
- while ((size = psi->read(&id, &type, &time)) > 0) {
+ while ((size = psi->read(&id, &type, &time, psi)) > 0) {
if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
- time, psi->erase))
+ time, psi))
failed++;
}
psi->close(psi);
@@ -196,10 +197,10 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
mutex_lock(&psinfo->buf_mutex);
memcpy(psinfo->buf, buf, size);
- id = psinfo->write(type, size);
+ id = psinfo->write(type, size, psinfo);
if (pstore_is_mounted())
pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
- size, CURRENT_TIME, psinfo->erase);
+ size, CURRENT_TIME, psinfo);
mutex_unlock(&psinfo->buf_mutex);
return 0;
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 2455ef2..b2f1d97 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -38,9 +38,11 @@ struct pstore_info {
int (*open)(struct pstore_info *psi);
int (*close)(struct pstore_info *psi);
ssize_t (*read)(u64 *id, enum pstore_type_id *type,
- struct timespec *time);
- u64 (*write)(enum pstore_type_id type, size_t size);
- int (*erase)(u64 id);
+ struct timespec *time, struct pstore_info *psi);
+ u64 (*write)(enum pstore_type_id type, size_t size,
+ struct pstore_info *psi);
+ int (*erase)(u64 id, struct pstore_info *psi);
+ void *data;
};
#ifdef CONFIG_PSTORE
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 2/9] pstore: Add extra context for writes and erases
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 1/9] pstore: Extend API Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 3/9] pstore: Make "part" unsigned Matthew Garrett
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett
EFI only provides small amounts of individual storage, and conventionally
puts metadata in the storage variable name. Rather than add a metadata
header to the (already limited) variable storage, it's easier for us to
modify pstore to pass all the information we need to construct a unique
variable name to the appropriate functions.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/acpi/apei/erst.c | 10 ++++++----
fs/pstore/inode.c | 6 ++++--
fs/pstore/platform.c | 9 +++++----
include/linux/pstore.h | 5 +++--
4 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 8aac55e..51cf7ba 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,9 +933,10 @@ static int erst_open_pstore(struct pstore_info *psi);
static int erst_close_pstore(struct pstore_info *psi);
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, size_t size,
+static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
struct pstore_info *psi);
-static int erst_clearer(u64 id, struct pstore_info *psi);
+static int erst_clearer(enum pstore_type_id type, u64 id,
+ struct pstore_info *psi);
static struct pstore_info erst_info = {
.owner = THIS_MODULE,
@@ -1039,7 +1040,7 @@ out:
return (rc < 0) ? rc : (len - sizeof(*rcd));
}
-static u64 erst_writer(enum pstore_type_id type, size_t size,
+static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
struct pstore_info *psi)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
@@ -1083,7 +1084,8 @@ static u64 erst_writer(enum pstore_type_id type, size_t size,
return rcd->hdr.record_id;
}
-static int erst_clearer(u64 id, struct pstore_info *psi)
+static int erst_clearer(enum pstore_type_id type, u64 id,
+ struct pstore_info *psi)
{
return erst_clear(id);
}
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c
index b19884a..893b961 100644
--- a/fs/pstore/inode.c
+++ b/fs/pstore/inode.c
@@ -39,8 +39,9 @@
#define PSTORE_NAMELEN 64
struct pstore_private {
- u64 id;
struct pstore_info *psi;
+ enum pstore_type_id type;
+ u64 id;
ssize_t size;
char data[];
};
@@ -73,7 +74,7 @@ static int pstore_unlink(struct inode *dir, struct dentry *dentry)
{
struct pstore_private *p = dentry->d_inode->i_private;
- p->psi->erase(p->id, p->psi);
+ p->psi->erase(p->type, p->id, p->psi);
return simple_unlink(dir, dentry);
}
@@ -192,6 +193,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id,
private = kmalloc(sizeof *private + size, GFP_KERNEL);
if (!private)
goto fail_alloc;
+ private->type = type;
private->id = id;
private->psi = psi;
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 221c04e..163bb40 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -78,7 +78,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
oopscount++;
while (total < kmsg_bytes) {
dst = psinfo->buf;
- hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++);
+ hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
size = psinfo->bufsize - hsize;
dst += hsize;
@@ -94,8 +94,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
memcpy(dst, s1 + s1_start, l1_cpy);
memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
- id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy,
- psinfo);
+ id = psinfo->write(PSTORE_TYPE_DMESG, part,
+ hsize + l1_cpy + l2_cpy, psinfo);
if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
psinfo->buf, hsize + l1_cpy + l2_cpy,
@@ -103,6 +103,7 @@ static void pstore_dump(struct kmsg_dumper *dumper,
l1 -= l1_cpy;
l2 -= l2_cpy;
total += l1_cpy + l2_cpy;
+ part++;
}
mutex_unlock(&psinfo->buf_mutex);
}
@@ -197,7 +198,7 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
mutex_lock(&psinfo->buf_mutex);
memcpy(psinfo->buf, buf, size);
- id = psinfo->write(type, size, psinfo);
+ id = psinfo->write(type, 0, size, psinfo);
if (pstore_is_mounted())
pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
size, CURRENT_TIME, psinfo);
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index b2f1d97..12be8f1 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,9 +39,10 @@ struct pstore_info {
int (*close)(struct pstore_info *psi);
ssize_t (*read)(u64 *id, enum pstore_type_id *type,
struct timespec *time, struct pstore_info *psi);
- u64 (*write)(enum pstore_type_id type, size_t size,
+ u64 (*write)(enum pstore_type_id type, int part,
+ size_t size, struct pstore_info *psi);
+ int (*erase)(enum pstore_type_id type, u64 id,
struct pstore_info *psi);
- int (*erase)(u64 id, struct pstore_info *psi);
void *data;
};
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 3/9] pstore: Make "part" unsigned
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 1/9] pstore: Extend API Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 2/9] pstore: Add extra context for writes and erases Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett
We'll never have a negative part, so just make this an unsigned int.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/acpi/apei/erst.c | 8 ++++----
fs/pstore/platform.c | 3 ++-
include/linux/pstore.h | 2 +-
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 51cf7ba..2ca59dc 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -933,8 +933,8 @@ static int erst_open_pstore(struct pstore_info *psi);
static int erst_close_pstore(struct pstore_info *psi);
static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
struct timespec *time, struct pstore_info *psi);
-static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
- struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+ size_t size, struct pstore_info *psi);
static int erst_clearer(enum pstore_type_id type, u64 id,
struct pstore_info *psi);
@@ -1040,8 +1040,8 @@ out:
return (rc < 0) ? rc : (len - sizeof(*rcd));
}
-static u64 erst_writer(enum pstore_type_id type, int part, size_t size,
- struct pstore_info *psi)
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+ size_t size, struct pstore_info *psi)
{
struct cper_pstore_record *rcd = (struct cper_pstore_record *)
(erst_info.buf - sizeof(*rcd));
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 163bb40..49ff1de 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -67,7 +67,8 @@ static void pstore_dump(struct kmsg_dumper *dumper,
unsigned long size, total = 0;
char *dst, *why;
u64 id;
- int hsize, part = 1;
+ int hsize;
+ unsigned int part = 1;
if (reason < ARRAY_SIZE(reason_str))
why = reason_str[reason];
diff --git a/include/linux/pstore.h b/include/linux/pstore.h
index 12be8f1..cc03bbf 100644
--- a/include/linux/pstore.h
+++ b/include/linux/pstore.h
@@ -39,7 +39,7 @@ struct pstore_info {
int (*close)(struct pstore_info *psi);
ssize_t (*read)(u64 *id, enum pstore_type_id *type,
struct timespec *time, struct pstore_info *psi);
- u64 (*write)(enum pstore_type_id type, int part,
+ u64 (*write)(enum pstore_type_id type, unsigned int part,
size_t size, struct pstore_info *psi);
int (*erase)(enum pstore_type_id type, u64 id,
struct pstore_info *psi);
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 4/9] pstore: Allow the user to explicitly choose a backend
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (2 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 3/9] pstore: Make "part" unsigned Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett
pstore only allows one backend to be registered at present, but the
system may provide several. Add a parameter to allow the user to choose
which backend will be used rather than just relying on load order.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
Documentation/ABI/testing/pstore | 6 ++++++
Documentation/kernel-parameters.txt | 2 ++
fs/pstore/platform.c | 11 +++++++++++
3 files changed, 19 insertions(+), 0 deletions(-)
diff --git a/Documentation/ABI/testing/pstore b/Documentation/ABI/testing/pstore
index ddf451e..ff1df4e 100644
--- a/Documentation/ABI/testing/pstore
+++ b/Documentation/ABI/testing/pstore
@@ -39,3 +39,9 @@ Description: Generic interface to platform dependent persistent storage.
multiple) files based on the record size of the underlying
persistent storage until at least this amount is reached.
Default is 10 Kbytes.
+
+ Pstore only supports one backend at a time. If multiple
+ backends are available, the preferred backend may be
+ set by passing the pstore.backend= argument to the kernel at
+ boot time.
+
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index ede3209..abafa88 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2156,6 +2156,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
[HW,MOUSE] Controls Logitech smartscroll autorepeat.
0 = disabled, 1 = enabled (default).
+ pstore.backend= Specify the name of the pstore backend to use
+
pt. [PARIDE]
See Documentation/blockdev/paride.txt.
diff --git a/fs/pstore/platform.c b/fs/pstore/platform.c
index 49ff1de..c5300ec 100644
--- a/fs/pstore/platform.c
+++ b/fs/pstore/platform.c
@@ -37,6 +37,8 @@
static DEFINE_SPINLOCK(pstore_lock);
static struct pstore_info *psinfo;
+static char *backend;
+
/* How much of the console log to snapshot */
static unsigned long kmsg_bytes = 10240;
@@ -131,6 +133,12 @@ int pstore_register(struct pstore_info *psi)
spin_unlock(&pstore_lock);
return -EBUSY;
}
+
+ if (backend && strcmp(backend, psi->name)) {
+ spin_unlock(&pstore_lock);
+ return -EINVAL;
+ }
+
psinfo = psi;
spin_unlock(&pstore_lock);
@@ -208,3 +216,6 @@ int pstore_write(enum pstore_type_id type, char *buf, size_t size)
return 0;
}
EXPORT_SYMBOL_GPL(pstore_write);
+
+module_param(backend, charp, 0444);
+MODULE_PARM_DESC(backend, "Pstore backend to use");
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 5/9] efi: Add support for using efivars as a pstore backend
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (3 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 6/9] efivars: String functions Matthew Garrett
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck, Matthew Garrett
EFI provides an area of nonvolatile storage managed by the firmware. We
can use this as a pstore backend to maintain copies of oopses, aiding
diagnosis.
Signed-off-by: Matthew Garrett <mjg@redhat.com>
---
drivers/firmware/efivars.c | 191 +++++++++++++++++++++++++++++++++++++++++++-
include/linux/efi.h | 6 ++
2 files changed, 195 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 5f29aaf..2bbb226 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -78,6 +78,7 @@
#include <linux/kobject.h>
#include <linux/device.h>
#include <linux/slab.h>
+#include <linux/pstore.h>
#include <asm/uaccess.h>
@@ -89,6 +90,8 @@ MODULE_DESCRIPTION("sysfs interface to EFI Variables");
MODULE_LICENSE("GPL");
MODULE_VERSION(EFIVARS_VERSION);
+#define DUMP_NAME_LEN 52
+
/*
* The maximum size of VariableName + Data = 1024
* Therefore, it's reasonable to save that much
@@ -161,18 +164,28 @@ utf8_strsize(efi_char16_t *data, unsigned long maxlength)
}
static efi_status_t
-get_var_data(struct efivars *efivars, struct efi_variable *var)
+get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
{
efi_status_t status;
- spin_lock(&efivars->lock);
var->DataSize = 1024;
status = efivars->ops->get_variable(var->VariableName,
&var->VendorGuid,
&var->Attributes,
&var->DataSize,
var->Data);
+ return status;
+}
+
+static efi_status_t
+get_var_data(struct efivars *efivars, struct efi_variable *var)
+{
+ efi_status_t status;
+
+ spin_lock(&efivars->lock);
+ status = get_var_data_locked(efivars, var);
spin_unlock(&efivars->lock);
+
if (status != EFI_SUCCESS) {
printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
status);
@@ -387,12 +400,176 @@ static struct kobj_type efivar_ktype = {
.default_attrs = def_attrs,
};
+static struct pstore_info efi_pstore_info;
+
static inline void
efivar_unregister(struct efivar_entry *var)
{
kobject_put(&var->kobj);
}
+#ifdef CONFIG_PSTORE
+
+static int efi_pstore_open(struct pstore_info *psi)
+{
+ struct efivars *efivars = psi->data;
+
+ spin_lock(&efivars->lock);
+ efivars->walk_entry = list_first_entry(&efivars->list,
+ struct efivar_entry, list);
+ return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+ struct efivars *efivars = psi->data;
+
+ spin_unlock(&efivars->lock);
+ return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+ struct timespec *timespec, struct pstore_info *psi)
+{
+ efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+ struct efivars *efivars = psi->data;
+ char name[DUMP_NAME_LEN];
+ int i;
+ unsigned int part, size;
+ unsigned long time;
+
+ while (&efivars->walk_entry->list != &efivars->list) {
+ if (!efi_guidcmp(efivars->walk_entry->var.VendorGuid,
+ vendor)) {
+ for (i = 0; i < DUMP_NAME_LEN; i++) {
+ name[i] = efivars->walk_entry->var.VariableName[i];
+ }
+ if (sscanf(name, "dump-type%u-%u-%lu", type, &part, &time) == 3) {
+ *id = part;
+ timespec->tv_sec = time;
+ timespec->tv_nsec = 0;
+ get_var_data_locked(efivars, &efivars->walk_entry->var);
+ size = efivars->walk_entry->var.DataSize;
+ memcpy(psi->buf, efivars->walk_entry->var.Data, size);
+ efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+ struct efivar_entry, list);
+ return size;
+ }
+ }
+ efivars->walk_entry = list_entry(efivars->walk_entry->list.next,
+ struct efivar_entry, list);
+ }
+ return 0;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
+ size_t size, struct pstore_info *psi)
+{
+ char name[DUMP_NAME_LEN];
+ char stub_name[DUMP_NAME_LEN];
+ efi_char16_t efi_name[DUMP_NAME_LEN];
+ efi_guid_t vendor = LINUX_EFI_CRASH_GUID;
+ struct efivars *efivars = psi->data;
+ struct efivar_entry *entry, *found = NULL;
+ int i;
+
+ sprintf(stub_name, "dump-type%u-%u-", type, part);
+ sprintf(name, "%s%lu", stub_name, get_seconds());
+
+ spin_lock(&efivars->lock);
+
+ for (i = 0; i < DUMP_NAME_LEN; i++)
+ efi_name[i] = stub_name[i];
+
+ /*
+ * Clean up any entries with the same name
+ */
+
+ list_for_each_entry(entry, &efivars->list, list) {
+ get_var_data_locked(efivars, &entry->var);
+
+ for (i = 0; i < DUMP_NAME_LEN; i++) {
+ if (efi_name[i] == 0) {
+ found = entry;
+ efivars->ops->set_variable(entry->var.VariableName,
+ &entry->var.VendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 0, NULL);
+ break;
+ } else if (efi_name[i] != entry->var.VariableName[i]) {
+ break;
+ }
+ }
+ }
+
+ if (found)
+ list_del(&found->list);
+
+ for (i = 0; i < DUMP_NAME_LEN; i++)
+ efi_name[i] = name[i];
+
+ efivars->ops->set_variable(efi_name, &vendor,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ size, psi->buf);
+
+ spin_unlock(&efivars->lock);
+
+ if (found)
+ efivar_unregister(found);
+
+ if (size)
+ efivar_create_sysfs_entry(efivars, utf8_strsize(efi_name, DUMP_NAME_LEN * 2),
+ efi_name, &vendor);
+
+ return part;
+};
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+ struct pstore_info *psi)
+{
+ efi_pstore_write(type, id, 0, psi);
+
+ return 0;
+}
+#else
+static int efi_pstore_open(struct pstore_info *psi)
+{
+ return 0;
+}
+
+static int efi_pstore_close(struct pstore_info *psi)
+{
+ return 0;
+}
+
+static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type,
+ struct timespec *time, struct pstore_info *psi)
+{
+ return -1;
+}
+
+static u64 efi_pstore_write(enum pstore_type_id type, int part, size_t size,
+ struct pstore_info *psi)
+{
+ return 0;
+}
+
+static int efi_pstore_erase(enum pstore_type_id type, u64 id,
+ struct pstore_info *psi)
+{
+ return 0;
+}
+#endif
+
+static struct pstore_info efi_pstore_info = {
+ .owner = THIS_MODULE,
+ .name = "efi",
+ .open = efi_pstore_open,
+ .close = efi_pstore_close,
+ .read = efi_pstore_read,
+ .write = efi_pstore_write,
+ .erase = efi_pstore_erase,
+};
static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr,
@@ -763,6 +940,16 @@ int register_efivars(struct efivars *efivars,
if (error)
unregister_efivars(efivars);
+ efivars->efi_pstore_info = efi_pstore_info;
+
+ efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+ if (efivars->efi_pstore_info.buf) {
+ efivars->efi_pstore_info.bufsize = 1024;
+ efivars->efi_pstore_info.data = efivars;
+ mutex_init(&efivars->efi_pstore_info.buf_mutex);
+ pstore_register(&efivars->efi_pstore_info);
+ }
+
out:
kfree(variable_name);
diff --git a/include/linux/efi.h b/include/linux/efi.h
index ec25726..2362a0b 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -19,6 +19,7 @@
#include <linux/rtc.h>
#include <linux/ioport.h>
#include <linux/pfn.h>
+#include <linux/pstore.h>
#include <asm/page.h>
#include <asm/system.h>
@@ -232,6 +233,9 @@ typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
#define UV_SYSTEM_TABLE_GUID \
EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
+#define LINUX_EFI_CRASH_GUID \
+ EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
+
typedef struct {
efi_guid_t guid;
unsigned long table;
@@ -458,6 +462,8 @@ struct efivars {
struct kset *kset;
struct bin_attribute *new_var, *del_var;
const struct efivar_operations *ops;
+ struct efivar_entry *walk_entry;
+ struct pstore_info efi_pstore_info;
};
int register_efivars(struct efivars *efivars,
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 6/9] efivars: String functions
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (4 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-08-02 16:48 ` Tony Luck
2011-07-21 20:57 ` [PATCH V2 7/9] efivars: introduce utf16_strncmp Matthew Garrett
` (3 subsequent siblings)
9 siblings, 1 reply; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck
From: Mike Waychison <mikew@google.com>
Fix the string functions in the efivars driver to be called utf16_*
instead of utf8_* as the encoding is utf16, not utf8.
As well, rename utf16_strlen to utf16_strnlen as it takes a maxlength
argument and the name should be consistent with the standard C function
names. utf16_strlen is still provided for convenience in a subsequent
patch.
Signed-off-by: Mike Waychison <mikew@google.com>
---
drivers/firmware/efivars.c | 30 +++++++++++++++++++-----------
1 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 2bbb226..4202a31 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -144,23 +144,29 @@ efivar_create_sysfs_entry(struct efivars *efivars,
/* Return the number of unicode characters in data */
static unsigned long
-utf8_strlen(efi_char16_t *data, unsigned long maxlength)
+utf16_strnlen(efi_char16_t *s, size_t maxlength)
{
unsigned long length = 0;
- while (*data++ != 0 && length < maxlength)
+ while (*s++ != 0 && length < maxlength)
length++;
return length;
}
+static unsigned long
+utf16_strlen(efi_char16_t *s)
+{
+ return utf16_strnlen(s, ~0UL);
+}
+
/*
* Return the number of bytes is the length of this string
* Note: this is NOT the same as the number of unicode characters
*/
static inline unsigned long
-utf8_strsize(efi_char16_t *data, unsigned long maxlength)
+utf16_strsize(efi_char16_t *data, unsigned long maxlength)
{
- return utf8_strlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
+ return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
}
static efi_status_t
@@ -518,7 +524,9 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
efivar_unregister(found);
if (size)
- efivar_create_sysfs_entry(efivars, utf8_strsize(efi_name, DUMP_NAME_LEN * 2),
+ efivar_create_sysfs_entry(efivars,
+ utf16_strsize(efi_name,
+ DUMP_NAME_LEN * 2),
efi_name, &vendor);
return part;
@@ -591,8 +599,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf8_strsize(new_var->VariableName, 1024);
+ strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = utf16_strsize(new_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
new_var->VariableName, strsize1) &&
@@ -624,8 +632,8 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
/* Create the entry in sysfs. Locking is not required here */
status = efivar_create_sysfs_entry(efivars,
- utf8_strsize(new_var->VariableName,
- 1024),
+ utf16_strsize(new_var->VariableName,
+ 1024),
new_var->VariableName,
&new_var->VendorGuid);
if (status) {
@@ -654,8 +662,8 @@ static ssize_t efivar_delete(struct file *filp, struct kobject *kobj,
* Does this variable already exist?
*/
list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
- strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
- strsize2 = utf8_strsize(del_var->VariableName, 1024);
+ strsize1 = utf16_strsize(search_efivar->var.VariableName, 1024);
+ strsize2 = utf16_strsize(del_var->VariableName, 1024);
if (strsize1 == strsize2 &&
!memcmp(&(search_efivar->var.VariableName),
del_var->VariableName, strsize1) &&
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 7/9] efivars: introduce utf16_strncmp
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (5 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 6/9] efivars: String functions Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 8/9] efivars: Use string functions in pstore_write Matthew Garrett
` (2 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck
From: Mike Waychison <mikew@google.com>
Introduce utf16_strncmp which is used in the next patch. Semantics
should be the same as the strncmp C function.
Signed-off-by: Mike Waychison <mikew@google.com>
---
drivers/firmware/efivars.c | 18 ++++++++++++++++++
1 files changed, 18 insertions(+), 0 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 4202a31..15b9a01 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -169,6 +169,24 @@ utf16_strsize(efi_char16_t *data, unsigned long maxlength)
return utf16_strnlen(data, maxlength/sizeof(efi_char16_t)) * sizeof(efi_char16_t);
}
+static inline int
+utf16_strncmp(const efi_char16_t *a, const efi_char16_t *b, size_t len)
+{
+ while (1) {
+ if (len == 0)
+ return 0;
+ if (*a < *b)
+ return -1;
+ if (*a > *b)
+ return 1;
+ if (*a == 0) /* implies *b == 0 */
+ return 0;
+ a++;
+ b++;
+ len--;
+ }
+}
+
static efi_status_t
get_var_data_locked(struct efivars *efivars, struct efi_variable *var)
{
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 8/9] efivars: Use string functions in pstore_write
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (6 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 7/9] efivars: introduce utf16_strncmp Matthew Garrett
@ 2011-07-21 20:57 ` Matthew Garrett
2011-07-21 20:58 ` [PATCH V2 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett
2011-07-21 23:06 ` Add efi variables as a pstore backend Mike Waychison
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:57 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck
From: Mike Waychison <mikew@google.com>
Instead of open-coding the string operations for comparing the prefix of
the variable names, use the provided utf16_* string functions.
This patch also changes the calls to efi.set_variable to
efivars->ops->set_variable so that the right function gets called in the
case of gsmi (which doesn't have a valid efi structure).
As well, make sure that we only consider variables with the right vendor
string.
Signed-off-by: Mike Waychison <mikew@google.com>
---
drivers/firmware/efivars.c | 26 ++++++++++++++------------
1 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 15b9a01..563492e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -512,18 +512,20 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
list_for_each_entry(entry, &efivars->list, list) {
get_var_data_locked(efivars, &entry->var);
- for (i = 0; i < DUMP_NAME_LEN; i++) {
- if (efi_name[i] == 0) {
- found = entry;
- efivars->ops->set_variable(entry->var.VariableName,
- &entry->var.VendorGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- 0, NULL);
- break;
- } else if (efi_name[i] != entry->var.VariableName[i]) {
- break;
- }
- }
+ if (efi_guidcmp(entry->var.VendorGuid, vendor))
+ continue;
+ if (utf16_strncmp(entry->var.VariableName, efi_name,
+ utf16_strlen(efi_name)))
+ continue;
+ /* Needs to be a prefix */
+ if (entry->var.VariableName[utf16_strlen(efi_name)] == 0)
+ continue;
+
+ /* found */
+ found = entry;
+ efivars->ops->set_variable(entry->var.VariableName, &entry->var.VendorGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ 0, NULL);
}
if (found)
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH V2 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (7 preceding siblings ...)
2011-07-21 20:57 ` [PATCH V2 8/9] efivars: Use string functions in pstore_write Matthew Garrett
@ 2011-07-21 20:58 ` Matthew Garrett
2011-07-21 23:06 ` Add efi variables as a pstore backend Mike Waychison
9 siblings, 0 replies; 12+ messages in thread
From: Matthew Garrett @ 2011-07-21 20:58 UTC (permalink / raw)
To: x86; +Cc: linux-kernel, mikew, tony.luck
From: Mike Waychison <mikew@google.com>
Consolidate the attributes listed for pstore operations in one place,
PSTORE_EFI_ATTRIBUTES.
Signed-off-by: Mike Waychison <mikew@google.com>
---
drivers/firmware/efivars.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 563492e..eacb05e 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -122,6 +122,10 @@ struct efivar_attribute {
ssize_t (*store)(struct efivar_entry *entry, const char *buf, size_t count);
};
+#define PSTORE_EFI_ATTRIBUTES \
+ (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS)
#define EFIVAR_ATTR(_name, _mode, _show, _store) \
struct efivar_attribute efivar_attr_##_name = { \
@@ -523,8 +527,9 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
/* found */
found = entry;
- efivars->ops->set_variable(entry->var.VariableName, &entry->var.VendorGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ efivars->ops->set_variable(entry->var.VariableName,
+ &entry->var.VendorGuid,
+ PSTORE_EFI_ATTRIBUTES,
0, NULL);
}
@@ -534,8 +539,7 @@ static u64 efi_pstore_write(enum pstore_type_id type, unsigned int part,
for (i = 0; i < DUMP_NAME_LEN; i++)
efi_name[i] = name[i];
- efivars->ops->set_variable(efi_name, &vendor,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ efivars->ops->set_variable(efi_name, &vendor, PSTORE_EFI_ATTRIBUTES,
size, psi->buf);
spin_unlock(&efivars->lock);
--
1.7.6
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Add efi variables as a pstore backend
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
` (8 preceding siblings ...)
2011-07-21 20:58 ` [PATCH V2 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett
@ 2011-07-21 23:06 ` Mike Waychison
9 siblings, 0 replies; 12+ messages in thread
From: Mike Waychison @ 2011-07-21 23:06 UTC (permalink / raw)
To: Matthew Garrett; +Cc: x86, linux-kernel, tony.luck
On Thu, Jul 21, 2011 at 1:57 PM, Matthew Garrett <mjg@redhat.com> wrote:
> The same as the last attempt, but with Tony's comments on patch 4 addressed.
>
>
I just read through these and it looks good to me.
We can deal with the unload side of things when needed.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH V2 6/9] efivars: String functions
2011-07-21 20:57 ` [PATCH V2 6/9] efivars: String functions Matthew Garrett
@ 2011-08-02 16:48 ` Tony Luck
0 siblings, 0 replies; 12+ messages in thread
From: Tony Luck @ 2011-08-02 16:48 UTC (permalink / raw)
To: Matthew Garrett; +Cc: x86, linux-kernel, mikew
On Thu, Jul 21, 2011 at 1:57 PM, Matthew Garrett <mjg@redhat.com> wrote:
> +static unsigned long
> +utf16_strlen(efi_char16_t *s)
> +{
> + return utf16_strnlen(s, ~0UL);
> +}
> +
When building with CONFIG_PSTORE=n, I see a warning:
drivers/firmware/efivars.c:161: warning: ‘utf16_strlen’ defined but not used
I can just slap:
#ifdef CONFIG_PSTORE
...
#endif
around this function definition - but I wondered if there was a better way
to fix it?
-Tony
Also with CONFIG_PSTORE=n I see:
drivers/firmware/efivars.c:602: warning: initialization from
incompatible pointer type
but that one just needs the stub definition of "efi_pstore_write" to
match the real
definition with "part" being unsigned.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2011-08-02 16:48 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-07-21 20:57 Add efi variables as a pstore backend Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 1/9] pstore: Extend API Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 2/9] pstore: Add extra context for writes and erases Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 3/9] pstore: Make "part" unsigned Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 4/9] pstore: Allow the user to explicitly choose a backend Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 5/9] efi: Add support for using efivars as a pstore backend Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 6/9] efivars: String functions Matthew Garrett
2011-08-02 16:48 ` Tony Luck
2011-07-21 20:57 ` [PATCH V2 7/9] efivars: introduce utf16_strncmp Matthew Garrett
2011-07-21 20:57 ` [PATCH V2 8/9] efivars: Use string functions in pstore_write Matthew Garrett
2011-07-21 20:58 ` [PATCH V2 9/9] efivars: Introduce PSTORE_EFI_ATTRIBUTES Matthew Garrett
2011-07-21 23:06 ` Add efi variables as a pstore backend Mike Waychison
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®