Path: blob/master/arch/powerpc/platforms/powernv/opal-secvar.c
26481 views
// SPDX-License-Identifier: GPL-2.01/*2* PowerNV code for secure variables3*4* Copyright (C) 2019 IBM Corporation5* Author: Claudio Carvalho6* Nayna Jain7*8* APIs to access secure variables managed by OPAL.9*/1011#define pr_fmt(fmt) "secvar: "fmt1213#include <linux/types.h>14#include <linux/of.h>15#include <linux/platform_device.h>16#include <asm/opal.h>17#include <asm/secvar.h>18#include <asm/secure_boot.h>1920static int opal_status_to_err(int rc)21{22int err;2324switch (rc) {25case OPAL_SUCCESS:26err = 0;27break;28case OPAL_UNSUPPORTED:29err = -ENXIO;30break;31case OPAL_PARAMETER:32err = -EINVAL;33break;34case OPAL_RESOURCE:35err = -ENOSPC;36break;37case OPAL_HARDWARE:38err = -EIO;39break;40case OPAL_NO_MEM:41err = -ENOMEM;42break;43case OPAL_EMPTY:44err = -ENOENT;45break;46case OPAL_PARTIAL:47err = -EFBIG;48break;49default:50err = -EINVAL;51}5253return err;54}5556static int opal_get_variable(const char *key, u64 ksize, u8 *data, u64 *dsize)57{58int rc;5960if (!key || !dsize)61return -EINVAL;6263*dsize = cpu_to_be64(*dsize);6465rc = opal_secvar_get(key, ksize, data, dsize);6667*dsize = be64_to_cpu(*dsize);6869return opal_status_to_err(rc);70}7172static int opal_get_next_variable(const char *key, u64 *keylen, u64 keybufsize)73{74int rc;7576if (!key || !keylen)77return -EINVAL;7879*keylen = cpu_to_be64(*keylen);8081rc = opal_secvar_get_next(key, keylen, keybufsize);8283*keylen = be64_to_cpu(*keylen);8485return opal_status_to_err(rc);86}8788static int opal_set_variable(const char *key, u64 ksize, u8 *data, u64 dsize)89{90int rc;9192if (!key || !data)93return -EINVAL;9495rc = opal_secvar_enqueue_update(key, ksize, data, dsize);9697return opal_status_to_err(rc);98}99100static ssize_t opal_secvar_format(char *buf, size_t bufsize)101{102ssize_t rc = 0;103struct device_node *node;104const char *format;105106node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");107if (!of_device_is_available(node)) {108rc = -ENODEV;109goto out;110}111112rc = of_property_read_string(node, "format", &format);113if (rc)114goto out;115116rc = snprintf(buf, bufsize, "%s", format);117118out:119of_node_put(node);120121return rc;122}123124static int opal_secvar_max_size(u64 *max_size)125{126int rc;127struct device_node *node;128129node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");130if (!node)131return -ENODEV;132133if (!of_device_is_available(node)) {134rc = -ENODEV;135goto out;136}137138rc = of_property_read_u64(node, "max-var-size", max_size);139140out:141of_node_put(node);142return rc;143}144145static const struct secvar_operations opal_secvar_ops = {146.get = opal_get_variable,147.get_next = opal_get_next_variable,148.set = opal_set_variable,149.format = opal_secvar_format,150.max_size = opal_secvar_max_size,151};152153static int opal_secvar_probe(struct platform_device *pdev)154{155if (!opal_check_token(OPAL_SECVAR_GET)156|| !opal_check_token(OPAL_SECVAR_GET_NEXT)157|| !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {158pr_err("OPAL doesn't support secure variables\n");159return -ENODEV;160}161162return set_secvar_ops(&opal_secvar_ops);163}164165static const struct of_device_id opal_secvar_match[] = {166{ .compatible = "ibm,secvar-backend",},167{},168};169170static struct platform_driver opal_secvar_driver = {171.driver = {172.name = "secvar",173.of_match_table = opal_secvar_match,174},175};176177static int __init opal_secvar_init(void)178{179return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);180}181device_initcall(opal_secvar_init);182183184