From a104a30593e45ec9418c4acf13d5cbc9f5944c42 Mon Sep 17 00:00:00 2001 From: Semen Protsenko Date: Fri, 5 Sep 2014 16:49:54 +0300 Subject: DO NOT MERGE: patch for testing UpdateCapsule() runtime service Change-Id: Ifa871bad23aceecc1c049e277df787f3616366fc Signed-off-by: Semen Protsenko --- drivers/Kconfig | 2 + drivers/Makefile | 2 + drivers/test_rs/Kconfig | 18 +++++ drivers/test_rs/Makefile | 1 + drivers/test_rs/update_capsule.c | 156 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 179 insertions(+) create mode 100644 drivers/test_rs/Kconfig create mode 100644 drivers/test_rs/Makefile create mode 100644 drivers/test_rs/update_capsule.c 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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 "); -- cgit v1.2.3