diff options
author | Semen Protsenko <semen.protsenko@linaro.org> | 2014-09-05 16:49:54 +0300 |
---|---|---|
committer | Graeme Gregory <graeme.gregory@linaro.org> | 2014-11-06 12:31:49 +0000 |
commit | 752d7567da77684daa9823902545d5e7a585b5b4 (patch) | |
tree | 91b5550b7f21d6141229c28e93e43146a0bf5870 | |
parent | 5fb39823b2d187d857bbe62e6df015bfa737de6e (diff) | |
download | leg-kernel-752d7567da77684daa9823902545d5e7a585b5b4.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/Kconfig | 2 | ||||
-rw-r--r-- | drivers/Makefile | 2 | ||||
-rw-r--r-- | drivers/test_rs/Kconfig | 18 | ||||
-rw-r--r-- | drivers/test_rs/Makefile | 1 | ||||
-rw-r--r-- | drivers/test_rs/update_capsule.c | 156 |
5 files changed, 179 insertions, 0 deletions
diff --git a/drivers/Kconfig b/drivers/Kconfig index 87a2552cafea..1a5973da93ac 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -186,4 +186,6 @@ source "drivers/thunderbolt/Kconfig" source "drivers/gator/Kconfig" +source "drivers/test_rs/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 48a5395ba400..9864f7fbbf82 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -164,3 +164,5 @@ obj-$(CONFIG_RAS) += ras/ obj-$(CONFIG_THUNDERBOLT) += thunderbolt/ obj-$(CONFIG_GATOR) += gator/ + +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>"); |