/* * 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 ");