19155e234SNayna Jain // SPDX-License-Identifier: GPL-2.0 29155e234SNayna Jain /* 39155e234SNayna Jain * PowerNV code for secure variables 49155e234SNayna Jain * 59155e234SNayna Jain * Copyright (C) 2019 IBM Corporation 69155e234SNayna Jain * Author: Claudio Carvalho 79155e234SNayna Jain * Nayna Jain 89155e234SNayna Jain * 99155e234SNayna Jain * APIs to access secure variables managed by OPAL. 109155e234SNayna Jain */ 119155e234SNayna Jain 129155e234SNayna Jain #define pr_fmt(fmt) "secvar: "fmt 139155e234SNayna Jain 149155e234SNayna Jain #include <linux/types.h> 159155e234SNayna Jain #include <linux/platform_device.h> 169155e234SNayna Jain #include <linux/of_platform.h> 179155e234SNayna Jain #include <asm/opal.h> 189155e234SNayna Jain #include <asm/secvar.h> 199155e234SNayna Jain #include <asm/secure_boot.h> 209155e234SNayna Jain 219155e234SNayna Jain static int opal_status_to_err(int rc) 229155e234SNayna Jain { 239155e234SNayna Jain int err; 249155e234SNayna Jain 259155e234SNayna Jain switch (rc) { 269155e234SNayna Jain case OPAL_SUCCESS: 279155e234SNayna Jain err = 0; 289155e234SNayna Jain break; 299155e234SNayna Jain case OPAL_UNSUPPORTED: 309155e234SNayna Jain err = -ENXIO; 319155e234SNayna Jain break; 329155e234SNayna Jain case OPAL_PARAMETER: 339155e234SNayna Jain err = -EINVAL; 349155e234SNayna Jain break; 359155e234SNayna Jain case OPAL_RESOURCE: 369155e234SNayna Jain err = -ENOSPC; 379155e234SNayna Jain break; 389155e234SNayna Jain case OPAL_HARDWARE: 399155e234SNayna Jain err = -EIO; 409155e234SNayna Jain break; 419155e234SNayna Jain case OPAL_NO_MEM: 429155e234SNayna Jain err = -ENOMEM; 439155e234SNayna Jain break; 449155e234SNayna Jain case OPAL_EMPTY: 459155e234SNayna Jain err = -ENOENT; 469155e234SNayna Jain break; 479155e234SNayna Jain case OPAL_PARTIAL: 489155e234SNayna Jain err = -EFBIG; 499155e234SNayna Jain break; 509155e234SNayna Jain default: 519155e234SNayna Jain err = -EINVAL; 529155e234SNayna Jain } 539155e234SNayna Jain 549155e234SNayna Jain return err; 559155e234SNayna Jain } 569155e234SNayna Jain 57*53cea34bSMichael Ellerman static int opal_get_variable(const char *key, u64 ksize, u8 *data, u64 *dsize) 589155e234SNayna Jain { 599155e234SNayna Jain int rc; 609155e234SNayna Jain 619155e234SNayna Jain if (!key || !dsize) 629155e234SNayna Jain return -EINVAL; 639155e234SNayna Jain 649155e234SNayna Jain *dsize = cpu_to_be64(*dsize); 659155e234SNayna Jain 669155e234SNayna Jain rc = opal_secvar_get(key, ksize, data, dsize); 679155e234SNayna Jain 689155e234SNayna Jain *dsize = be64_to_cpu(*dsize); 699155e234SNayna Jain 709155e234SNayna Jain return opal_status_to_err(rc); 719155e234SNayna Jain } 729155e234SNayna Jain 73*53cea34bSMichael Ellerman static int opal_get_next_variable(const char *key, u64 *keylen, u64 keybufsize) 749155e234SNayna Jain { 759155e234SNayna Jain int rc; 769155e234SNayna Jain 779155e234SNayna Jain if (!key || !keylen) 789155e234SNayna Jain return -EINVAL; 799155e234SNayna Jain 809155e234SNayna Jain *keylen = cpu_to_be64(*keylen); 819155e234SNayna Jain 829155e234SNayna Jain rc = opal_secvar_get_next(key, keylen, keybufsize); 839155e234SNayna Jain 849155e234SNayna Jain *keylen = be64_to_cpu(*keylen); 859155e234SNayna Jain 869155e234SNayna Jain return opal_status_to_err(rc); 879155e234SNayna Jain } 889155e234SNayna Jain 89*53cea34bSMichael Ellerman static int opal_set_variable(const char *key, u64 ksize, u8 *data, u64 dsize) 909155e234SNayna Jain { 919155e234SNayna Jain int rc; 929155e234SNayna Jain 939155e234SNayna Jain if (!key || !data) 949155e234SNayna Jain return -EINVAL; 959155e234SNayna Jain 969155e234SNayna Jain rc = opal_secvar_enqueue_update(key, ksize, data, dsize); 979155e234SNayna Jain 989155e234SNayna Jain return opal_status_to_err(rc); 999155e234SNayna Jain } 1009155e234SNayna Jain 1019155e234SNayna Jain static const struct secvar_operations opal_secvar_ops = { 1029155e234SNayna Jain .get = opal_get_variable, 1039155e234SNayna Jain .get_next = opal_get_next_variable, 1049155e234SNayna Jain .set = opal_set_variable, 1059155e234SNayna Jain }; 1069155e234SNayna Jain 1079155e234SNayna Jain static int opal_secvar_probe(struct platform_device *pdev) 1089155e234SNayna Jain { 1099155e234SNayna Jain if (!opal_check_token(OPAL_SECVAR_GET) 1109155e234SNayna Jain || !opal_check_token(OPAL_SECVAR_GET_NEXT) 1119155e234SNayna Jain || !opal_check_token(OPAL_SECVAR_ENQUEUE_UPDATE)) { 1129155e234SNayna Jain pr_err("OPAL doesn't support secure variables\n"); 1139155e234SNayna Jain return -ENODEV; 1149155e234SNayna Jain } 1159155e234SNayna Jain 1169155e234SNayna Jain set_secvar_ops(&opal_secvar_ops); 1179155e234SNayna Jain 1189155e234SNayna Jain return 0; 1199155e234SNayna Jain } 1209155e234SNayna Jain 1219155e234SNayna Jain static const struct of_device_id opal_secvar_match[] = { 1229155e234SNayna Jain { .compatible = "ibm,secvar-backend",}, 1239155e234SNayna Jain {}, 1249155e234SNayna Jain }; 1259155e234SNayna Jain 1269155e234SNayna Jain static struct platform_driver opal_secvar_driver = { 1279155e234SNayna Jain .driver = { 1289155e234SNayna Jain .name = "secvar", 1299155e234SNayna Jain .of_match_table = opal_secvar_match, 1309155e234SNayna Jain }, 1319155e234SNayna Jain }; 1329155e234SNayna Jain 1339155e234SNayna Jain static int __init opal_secvar_init(void) 1349155e234SNayna Jain { 1359155e234SNayna Jain return platform_driver_probe(&opal_secvar_driver, opal_secvar_probe); 1369155e234SNayna Jain } 1379155e234SNayna Jain device_initcall(opal_secvar_init); 138