123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * PowerNV code for secure variables
- *
- * Copyright (C) 2019 IBM Corporation
- * Author: Claudio Carvalho
- * Nayna Jain
- *
- * APIs to access secure variables managed by OPAL.
- */
- #define pr_fmt(fmt) "secvar: "fmt
- #include <linux/types.h>
- #include <linux/platform_device.h>
- #include <linux/of_platform.h>
- #include <asm/opal.h>
- #include <asm/secvar.h>
- #include <asm/secure_boot.h>
- static int opal_status_to_err(int rc)
- {
- int err;
- switch (rc) {
- case OPAL_SUCCESS:
- err = 0;
- break;
- case OPAL_UNSUPPORTED:
- err = -ENXIO;
- break;
- case OPAL_PARAMETER:
- err = -EINVAL;
- break;
- case OPAL_RESOURCE:
- err = -ENOSPC;
- break;
- case OPAL_HARDWARE:
- err = -EIO;
- break;
- case OPAL_NO_MEM:
- err = -ENOMEM;
- break;
- case OPAL_EMPTY:
- err = -ENOENT;
- break;
- case OPAL_PARTIAL:
- err = -EFBIG;
- break;
- default:
- err = -EINVAL;
- }
- return err;
- }
- static int opal_get_variable(const char *key, uint64_t ksize,
- u8 *data, uint64_t *dsize)
- {
- int rc;
- if (!key || !dsize)
- return -EINVAL;
- *dsize = cpu_to_be64(*dsize);
- rc = opal_secvar_get(key, ksize, data, dsize);
- *dsize = be64_to_cpu(*dsize);
- return opal_status_to_err(rc);
- }
- static int opal_get_next_variable(const char *key, uint64_t *keylen,
- uint64_t keybufsize)
- {
- int rc;
- if (!key || !keylen)
- return -EINVAL;
- *keylen = cpu_to_be64(*keylen);
- rc = opal_secvar_get_next(key, keylen, keybufsize);
- *keylen = be64_to_cpu(*keylen);
- return opal_status_to_err(rc);
- }
- static int opal_set_variable(const char *key, uint64_t ksize, u8 *data,
- uint64_t dsize)
- {
- int rc;
- if (!key || !data)
- return -EINVAL;
- rc = opal_secvar_enqueue_update(key, ksize, data, dsize);
- return opal_status_to_err(rc);
- }
- static const struct secvar_operations opal_secvar_ops = {
- .get = opal_get_variable,
- .get_next = opal_get_next_variable,
- .set = opal_set_variable,
- };
- static int opal_secvar_probe(struct platform_device *pdev)
- {
- if (!opal_check_token(OPAL_SECVAR_GET)
- || !opal_check_token(OPAL_SECVAR_GET_NEXT)
- || !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {
- pr_err("OPAL doesn't support secure variables\n");
- return -ENODEV;
- }
- set_secvar_ops(&opal_secvar_ops);
- return 0;
- }
- static const struct of_device_id opal_secvar_match[] = {
- { .compatible = "ibm,secvar-backend",},
- {},
- };
- static struct platform_driver opal_secvar_driver = {
- .driver = {
- .name = "secvar",
- .of_match_table = opal_secvar_match,
- },
- };
- static int __init opal_secvar_init(void)
- {
- return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);
- }
- device_initcall(opal_secvar_init);
|