// 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 #include #include #include #include #include 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);