cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

opal-secvar.c (2620B)


      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/platform_device.h>
     16#include <linux/of_platform.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, uint64_t ksize,
     58			     u8 *data, uint64_t *dsize)
     59{
     60	int rc;
     61
     62	if (!key || !dsize)
     63		return -EINVAL;
     64
     65	*dsize = cpu_to_be64(*dsize);
     66
     67	rc = opal_secvar_get(key, ksize, data, dsize);
     68
     69	*dsize = be64_to_cpu(*dsize);
     70
     71	return opal_status_to_err(rc);
     72}
     73
     74static int opal_get_next_variable(const char *key, uint64_t *keylen,
     75				  uint64_t keybufsize)
     76{
     77	int rc;
     78
     79	if (!key || !keylen)
     80		return -EINVAL;
     81
     82	*keylen = cpu_to_be64(*keylen);
     83
     84	rc = opal_secvar_get_next(key, keylen, keybufsize);
     85
     86	*keylen = be64_to_cpu(*keylen);
     87
     88	return opal_status_to_err(rc);
     89}
     90
     91static int opal_set_variable(const char *key, uint64_t ksize, u8 *data,
     92			     uint64_t dsize)
     93{
     94	int rc;
     95
     96	if (!key || !data)
     97		return -EINVAL;
     98
     99	rc = opal_secvar_enqueue_update(key, ksize, data, dsize);
    100
    101	return opal_status_to_err(rc);
    102}
    103
    104static const struct secvar_operations opal_secvar_ops = {
    105	.get = opal_get_variable,
    106	.get_next = opal_get_next_variable,
    107	.set = opal_set_variable,
    108};
    109
    110static int opal_secvar_probe(struct platform_device *pdev)
    111{
    112	if (!opal_check_token(OPAL_SECVAR_GET)
    113			|| !opal_check_token(OPAL_SECVAR_GET_NEXT)
    114			|| !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {
    115		pr_err("OPAL doesn't support secure variables\n");
    116		return -ENODEV;
    117	}
    118
    119	set_secvar_ops(&opal_secvar_ops);
    120
    121	return 0;
    122}
    123
    124static const struct of_device_id opal_secvar_match[] = {
    125	{ .compatible = "ibm,secvar-backend",},
    126	{},
    127};
    128
    129static struct platform_driver opal_secvar_driver = {
    130	.driver = {
    131		.name = "secvar",
    132		.of_match_table = opal_secvar_match,
    133	},
    134};
    135
    136static int __init opal_secvar_init(void)
    137{
    138	return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);
    139}
    140device_initcall(opal_secvar_init);