aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSemen Protsenko <semen.protsenko@linaro.org>2014-09-05 16:49:54 +0300
committerGraeme Gregory <graeme.gregory@linaro.org>2015-07-07 13:48:15 +0100
commitef0d76e5bbe50bc00627bec3b692318043a13b8f (patch)
tree1b069d4144e4f496ace0865c5400139b093ecf62
parentd770e558e21961ad6cfdf0ff7df0eb5d7d4f0754 (diff)
downloadleg-kernel-ef0d76e5bbe50bc00627bec3b692318043a13b8f.tar.gz
DO NOT MERGE: patch for testing UpdateCapsule() runtime service
Change-Id: Ifa871bad23aceecc1c049e277df787f3616366fc Signed-off-by: Semen Protsenko <semen.protsenko@linaro.org>
-rw-r--r--drivers/Kconfig2
-rw-r--r--drivers/Makefile2
-rw-r--r--drivers/test_rs/Kconfig18
-rw-r--r--drivers/test_rs/Makefile1
-rw-r--r--drivers/test_rs/update_capsule.c156
5 files changed, 179 insertions, 0 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig
index 6e973b8e3a3b..a8aff236a87e 100644
--- a/drivers/Kconfig
+++ b/drivers/Kconfig
@@ -184,4 +184,6 @@ source "drivers/android/Kconfig"
source "drivers/nvdimm/Kconfig"
+source "drivers/test_rs/Kconfig"
+
endmenu
diff --git a/drivers/Makefile b/drivers/Makefile
index b64b49f6e01b..e47e784a89c5 100644
--- a/drivers/Makefile
+++ b/drivers/Makefile
@@ -165,3 +165,5 @@ obj-$(CONFIG_RAS) += ras/
obj-$(CONFIG_THUNDERBOLT) += thunderbolt/
obj-$(CONFIG_CORESIGHT) += hwtracing/coresight/
obj-$(CONFIG_ANDROID) += android/
+
+obj-$(CONFIG_TEST_RS) += test_rs/
diff --git a/drivers/test_rs/Kconfig b/drivers/test_rs/Kconfig
new file mode 100644
index 000000000000..840dbcbc9511
--- /dev/null
+++ b/drivers/test_rs/Kconfig
@@ -0,0 +1,18 @@
+menuconfig TEST_RS
+ tristate "Test UEFI Runtime Services support"
+ default y
+ help
+ This option enables UEFI Runtime Services testing support.
+ Testing RS may require additional patches to UEFI code.
+ General approach is to read from corresponding sysfs entry
+ which will execute Runtime Service. UEFI in it's turn
+ will print some debug text to console. Next this text can be
+ parsed and one can tell from it if everything is working.
+ This way testing can be automated.
+
+config TEST_UPDATE_CAPSULE
+ tristate "Test UpdateCapsule RS"
+ depends on TEST_RS != n
+ default y
+ help
+ Enables capability to test UpdateCapsule() Runtime Service.
diff --git a/drivers/test_rs/Makefile b/drivers/test_rs/Makefile
new file mode 100644
index 000000000000..b0e65fc9a0bb
--- /dev/null
+++ b/drivers/test_rs/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TEST_UPDATE_CAPSULE) += update_capsule.o
diff --git a/drivers/test_rs/update_capsule.c b/drivers/test_rs/update_capsule.c
new file mode 100644
index 000000000000..b856215958af
--- /dev/null
+++ b/drivers/test_rs/update_capsule.c
@@ -0,0 +1,156 @@
+/*
+ * Test Update Capsule module.
+ *
+ * Copyright (C) 2014 Linaro
+ * Author: Sam Protsenko <semen.protsenko@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/efi.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kobject.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/sysfs.h>
+
+#define TRS_DIR_NAME "test_uefi_rs"
+
+static ssize_t tuc_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf);
+
+static struct kobject *trs_kobj;
+static struct kobj_attribute tuc_attribute = __ATTR_RO(tuc);
+static struct attribute *tuc_attrs[] = {
+ &tuc_attribute.attr,
+ NULL
+};
+static struct attribute_group tuc_attr_group = {
+ .attrs = tuc_attrs
+};
+static DEFINE_MUTEX(tuc_mutex);
+
+static int invoke_update_capsule(void *fw_buf)
+{
+ typedef struct {
+ u32 data1;
+ u16 data2;
+ u16 data3;
+ u8 data4[8];
+ } efi_guid2_t;
+
+ efi_capsule_header_t *capsules;
+ int i, j;
+ efi_guid2_t guid[2];
+ efi_status_t status;
+
+ capsules = kzalloc(2 * sizeof(efi_capsule_header_t), GFP_KERNEL);
+ if (capsules == NULL) {
+ pr_err("tuc: Unable to allocate memory for capsules\n");
+ return -ENOMEM;
+ }
+ for (i = 0; i < 2; ++i) {
+ guid[i].data1 = 111;
+ guid[i].data2 = 222;
+ guid[i].data3 = 333;
+ for (j = 0; j < 8; ++j)
+ guid[i].data4[j] = j + (i+1)*10;
+
+ capsules[i].guid = *(efi_guid_t *)(&(guid[i]));
+ capsules[i].headersize = sizeof(efi_capsule_header_t);
+ capsules[i].imagesize = 0;
+ }
+ capsules[0].flags = (u32)(u64)fw_buf;
+ capsules[1].flags = (u32)(((u64)fw_buf >> 32));
+
+ /* UEFI RS invokation */
+ status = efi.update_capsule(&capsules, 2, 0);
+ if (status != EFI_SUCCESS)
+ pr_err("tuc: error runtime service status: %lu\n", status);
+
+ kfree(capsules);
+
+ return 0;
+}
+
+/* Display info from this sysfs entry (cat ...) */
+static ssize_t tuc_show(struct kobject *kobj, struct kobj_attribute *attr,
+ char *buf)
+{
+ void *fw_buf;
+ int len;
+ int ret;
+
+ mutex_lock(&tuc_mutex);
+ fw_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (fw_buf == NULL) {
+ pr_err("tuc: Unable to allocate memory for shared memory\n");
+ mutex_unlock(&tuc_mutex);
+ return -ENOMEM;
+ }
+
+ ret = invoke_update_capsule(fw_buf);
+ if (ret) {
+ len = -ENOMEM;
+ goto err;
+ }
+
+ len = sprintf(buf, "%s", (char *)fw_buf);
+ if (len <= 0)
+ pr_err("tuc: Invalid sprintf len: %d\n", len);
+
+err:
+ kfree(fw_buf);
+ mutex_unlock(&tuc_mutex);
+ return len;
+}
+
+static int __init tuc_init_sysfs(void)
+{
+ int ret = 0;
+
+ trs_kobj = kobject_create_and_add(TRS_DIR_NAME, trs_kobj);
+ if (!trs_kobj) {
+ pr_err("tuc: unable to allocate memory for sysfs kobj\n");
+ return -ENOMEM;
+ }
+
+ ret = sysfs_create_group(trs_kobj, &tuc_attr_group);
+ if (ret) {
+ pr_err("tuc: sysfs creation failed\n");
+ kobject_put(trs_kobj);
+ }
+
+ return ret;
+}
+
+static int __init tuc_init(void)
+{
+ int ret;
+
+ ret = tuc_init_sysfs();
+ if (ret) {
+ pr_err("tuc: unable to initialize sysfs\n");
+ return ret;
+ }
+
+ pr_info("tuc: successfully loaded\n");
+ return 0;
+}
+
+static void __exit tuc_exit(void)
+{
+ kobject_put(trs_kobj);
+ pr_info("tuc: unloaded\n");
+}
+
+module_init(tuc_init);
+module_exit(tuc_exit);
+
+MODULE_DESCRIPTION("Test Update Capsule Module");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Sam Protsenko <semen.protsenko@linaro.org>");