Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * PowerNV code for secure variables
0004  *
0005  * Copyright (C) 2019 IBM Corporation
0006  * Author: Claudio Carvalho
0007  *         Nayna Jain
0008  *
0009  * APIs to access secure variables managed by OPAL.
0010  */
0011 
0012 #define pr_fmt(fmt) "secvar: "fmt
0013 
0014 #include <linux/types.h>
0015 #include <linux/platform_device.h>
0016 #include <linux/of_platform.h>
0017 #include <asm/opal.h>
0018 #include <asm/secvar.h>
0019 #include <asm/secure_boot.h>
0020 
0021 static int opal_status_to_err(int rc)
0022 {
0023     int err;
0024 
0025     switch (rc) {
0026     case OPAL_SUCCESS:
0027         err = 0;
0028         break;
0029     case OPAL_UNSUPPORTED:
0030         err = -ENXIO;
0031         break;
0032     case OPAL_PARAMETER:
0033         err = -EINVAL;
0034         break;
0035     case OPAL_RESOURCE:
0036         err = -ENOSPC;
0037         break;
0038     case OPAL_HARDWARE:
0039         err = -EIO;
0040         break;
0041     case OPAL_NO_MEM:
0042         err = -ENOMEM;
0043         break;
0044     case OPAL_EMPTY:
0045         err = -ENOENT;
0046         break;
0047     case OPAL_PARTIAL:
0048         err = -EFBIG;
0049         break;
0050     default:
0051         err = -EINVAL;
0052     }
0053 
0054     return err;
0055 }
0056 
0057 static int opal_get_variable(const char *key, uint64_t ksize,
0058                  u8 *data, uint64_t *dsize)
0059 {
0060     int rc;
0061 
0062     if (!key || !dsize)
0063         return -EINVAL;
0064 
0065     *dsize = cpu_to_be64(*dsize);
0066 
0067     rc = opal_secvar_get(key, ksize, data, dsize);
0068 
0069     *dsize = be64_to_cpu(*dsize);
0070 
0071     return opal_status_to_err(rc);
0072 }
0073 
0074 static int opal_get_next_variable(const char *key, uint64_t *keylen,
0075                   uint64_t keybufsize)
0076 {
0077     int rc;
0078 
0079     if (!key || !keylen)
0080         return -EINVAL;
0081 
0082     *keylen = cpu_to_be64(*keylen);
0083 
0084     rc = opal_secvar_get_next(key, keylen, keybufsize);
0085 
0086     *keylen = be64_to_cpu(*keylen);
0087 
0088     return opal_status_to_err(rc);
0089 }
0090 
0091 static int opal_set_variable(const char *key, uint64_t ksize, u8 *data,
0092                  uint64_t dsize)
0093 {
0094     int rc;
0095 
0096     if (!key || !data)
0097         return -EINVAL;
0098 
0099     rc = opal_secvar_enqueue_update(key, ksize, data, dsize);
0100 
0101     return opal_status_to_err(rc);
0102 }
0103 
0104 static const struct secvar_operations opal_secvar_ops = {
0105     .get = opal_get_variable,
0106     .get_next = opal_get_next_variable,
0107     .set = opal_set_variable,
0108 };
0109 
0110 static int opal_secvar_probe(struct platform_device *pdev)
0111 {
0112     if (!opal_check_token(OPAL_SECVAR_GET)
0113             || !opal_check_token(OPAL_SECVAR_GET_NEXT)
0114             || !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) {
0115         pr_err("OPAL doesn't support secure variables\n");
0116         return -ENODEV;
0117     }
0118 
0119     set_secvar_ops(&opal_secvar_ops);
0120 
0121     return 0;
0122 }
0123 
0124 static const struct of_device_id opal_secvar_match[] = {
0125     { .compatible = "ibm,secvar-backend",},
0126     {},
0127 };
0128 
0129 static struct platform_driver opal_secvar_driver = {
0130     .driver = {
0131         .name = "secvar",
0132         .of_match_table = opal_secvar_match,
0133     },
0134 };
0135 
0136 static int __init opal_secvar_init(void)
0137 {
0138     return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe);
0139 }
0140 device_initcall(opal_secvar_init);