linux/arch/powerpc/platforms/powernv/opal-secvar.c
<<
>>
Prefs
   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);
 141