File Index
Files and directories
Sign in
FILE

opal-secvar.c

File preview with syntax highlighting.

linux-6.19.14/arch/powerpc/platforms/powernv/opal-secvar.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * PowerNV code for secure variables
  4 *
  5 * Copyright (C) 2019 IBM Corporation
  6 * Author: Claudio Carvalho
  7 *         Nayna Jain
  8 *
  9 * APIs to access secure variables managed by OPAL.
 10 */
 11
 12#define pr_fmt(fmt) "secvar: "fmt
 13
 14#include <linux/types.h>
 15#include <linux/of.h>
 16#include <linux/platform_device.h>
 17#include <asm/opal.h>
 18#include <asm/secvar.h>
 19#include <asm/secure_boot.h>
 20
 21static int opal_status_to_err(int rc)
 22{
 23	int err;
 24
 25	switch (rc) {
 26	case OPAL_SUCCESS:
 27		err = 0;
 28		break;
 29	case OPAL_UNSUPPORTED:
 30		err = -ENXIO;
 31		break;
 32	case OPAL_PARAMETER:
 33		err = -EINVAL;
 34		break;
 35	case OPAL_RESOURCE:
 36		err = -ENOSPC;
 37		break;
 38	case OPAL_HARDWARE:
 39		err = -EIO;
 40		break;
 41	case OPAL_NO_MEM:
 42		err = -ENOMEM;
 43		break;
 44	case OPAL_EMPTY:
 45		err = -ENOENT;
 46		break;
 47	case OPAL_PARTIAL:
 48		err = -EFBIG;
 49		break;
 50	default:
 51		err = -EINVAL;
 52	}
 53
 54	return err;
 55}
 56
 57static int opal_get_variable(const char *key, u64 ksize, u8 *data, u64 *dsize)
 58{
 59	int rc;
 60
 61	if (!key || !dsize)
 62		return -EINVAL;
 63
 64	*dsize = cpu_to_be64(*dsize);
 65
 66	rc = opal_secvar_get(key, ksize, data, dsize);
 67
 68	*dsize = be64_to_cpu(*dsize);
 69
 70	return opal_status_to_err(rc);
 71}
 72
 73static int opal_get_next_variable(const char *key, u64 *keylen, u64 keybufsize)
 74{
 75	int rc;
 76
 77	if (!key || !keylen)
 78		return -EINVAL;
 79
 80	*keylen = cpu_to_be64(*keylen);
 81
 82	rc = opal_secvar_get_next(key, keylen, keybufsize);
 83
 84	*keylen = be64_to_cpu(*keylen);
 85
 86	return opal_status_to_err(rc);
 87}
 88
 89static int opal_set_variable(const char *key, u64 ksize, u8 *data, u64 dsize)
 90{
 91	int rc;
 92
 93	if (!key || !data)
 94		return -EINVAL;
 95
 96	rc = opal_secvar_enqueue_update(key, ksize, data, dsize);
 97
 98	return opal_status_to_err(rc);
 99}
100
101static ssize_t opal_secvar_format(char *buf, size_t bufsize)
102{
103	ssize_t rc = 0;
104	struct device_node *node;
105	const char *format;
106
107	node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
108	if (!of_device_is_available(node)) {
109		rc = -ENODEV;
110		goto out;
111	}
112
113	rc = of_property_read_string(node, "format", &format);
114	if (rc)
115		goto out;
116
117	rc = snprintf(buf, bufsize, "%s", format);
118
119out:
120	of_node_put(node);
121
122	return rc;
123}
124
125static int opal_secvar_max_size(u64 *max_size)
126{
127	int rc;
128	struct device_node *node;
129
130	node = of_find_compatible_node(NULL, NULL, "ibm,secvar-backend");
131	if (!node)
132		return -ENODEV;
133
134	if (!of_device_is_available(node)) {
135		rc = -ENODEV;
136		goto out;
137	}
138
139	rc = of_property_read_u64(node, "max-var-size", max_size);
140
141out:
142	of_node_put(node);
143	return rc;
144}
145
146static const struct secvar_operations opal_secvar_ops = {
147	.get = opal_get_variable,
148	.get_next = opal_get_next_variable,
149	.set = opal_set_variable,
150	.format = opal_secvar_format,
151	.max_size = opal_secvar_max_size,
152};
153
154static int opal_secvar_probe(struct platform_device *pdev)
155{
156	if (!opal_check_token(OPAL_SECVAR_GET)
157			|| !opal_check_token(OPAL_SECVAR_GET_NEXT)
158			|| !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {
159		pr_err("OPAL doesn't support secure variables\n");
160		return -ENODEV;
161	}
162
163	return set_secvar_ops(&opal_secvar_ops);
164}
165
166static const struct of_device_id opal_secvar_match[] = {
167	{ .compatible = "ibm,secvar-backend",},
168	{},
169};
170
171static struct platform_driver opal_secvar_driver = {
172	.driver = {
173		.name = "secvar",
174		.of_match_table = opal_secvar_match,
175	},
176};
177
178static int __init opal_secvar_init(void)
179{
180	return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);
181}
182device_initcall(opal_secvar_init);
~/ Read-only file preview.