1bdf86d0eSRuss Weight // SPDX-License-Identifier: GPL-2.0 2bdf86d0eSRuss Weight /* 3bdf86d0eSRuss Weight * Intel MAX10 Board Management Controller Secure Update Driver 4bdf86d0eSRuss Weight * 5bdf86d0eSRuss Weight * Copyright (C) 2019-2022 Intel Corporation. All rights reserved. 6bdf86d0eSRuss Weight * 7bdf86d0eSRuss Weight */ 8bdf86d0eSRuss Weight #include <linux/bitfield.h> 9bdf86d0eSRuss Weight #include <linux/device.h> 10bdf86d0eSRuss Weight #include <linux/firmware.h> 11bdf86d0eSRuss Weight #include <linux/mfd/intel-m10-bmc.h> 12bdf86d0eSRuss Weight #include <linux/mod_devicetable.h> 13bdf86d0eSRuss Weight #include <linux/module.h> 14bdf86d0eSRuss Weight #include <linux/platform_device.h> 15bdf86d0eSRuss Weight #include <linux/slab.h> 16bdf86d0eSRuss Weight 17bdf86d0eSRuss Weight struct m10bmc_sec { 18bdf86d0eSRuss Weight struct device *dev; 19bdf86d0eSRuss Weight struct intel_m10bmc *m10bmc; 20bdf86d0eSRuss Weight }; 21bdf86d0eSRuss Weight 22bdf86d0eSRuss Weight /* Root Entry Hash (REH) support */ 23bdf86d0eSRuss Weight #define REH_SHA256_SIZE 32 24bdf86d0eSRuss Weight #define REH_SHA384_SIZE 48 25bdf86d0eSRuss Weight #define REH_MAGIC GENMASK(15, 0) 26bdf86d0eSRuss Weight #define REH_SHA_NUM_BYTES GENMASK(31, 16) 27bdf86d0eSRuss Weight 28bdf86d0eSRuss Weight static ssize_t 29bdf86d0eSRuss Weight show_root_entry_hash(struct device *dev, u32 exp_magic, 30bdf86d0eSRuss Weight u32 prog_addr, u32 reh_addr, char *buf) 31bdf86d0eSRuss Weight { 32bdf86d0eSRuss Weight struct m10bmc_sec *sec = dev_get_drvdata(dev); 33bdf86d0eSRuss Weight int sha_num_bytes, i, ret, cnt = 0; 34bdf86d0eSRuss Weight u8 hash[REH_SHA384_SIZE]; 35bdf86d0eSRuss Weight unsigned int stride; 36bdf86d0eSRuss Weight u32 magic; 37bdf86d0eSRuss Weight 38bdf86d0eSRuss Weight stride = regmap_get_reg_stride(sec->m10bmc->regmap); 39bdf86d0eSRuss Weight ret = m10bmc_raw_read(sec->m10bmc, prog_addr, &magic); 40bdf86d0eSRuss Weight if (ret) 41bdf86d0eSRuss Weight return ret; 42bdf86d0eSRuss Weight 43bdf86d0eSRuss Weight if (FIELD_GET(REH_MAGIC, magic) != exp_magic) 44bdf86d0eSRuss Weight return sysfs_emit(buf, "hash not programmed\n"); 45bdf86d0eSRuss Weight 46bdf86d0eSRuss Weight sha_num_bytes = FIELD_GET(REH_SHA_NUM_BYTES, magic) / 8; 47bdf86d0eSRuss Weight if ((sha_num_bytes % stride) || 48bdf86d0eSRuss Weight (sha_num_bytes != REH_SHA256_SIZE && 49bdf86d0eSRuss Weight sha_num_bytes != REH_SHA384_SIZE)) { 50bdf86d0eSRuss Weight dev_err(sec->dev, "%s bad sha num bytes %d\n", __func__, 51bdf86d0eSRuss Weight sha_num_bytes); 52bdf86d0eSRuss Weight return -EINVAL; 53bdf86d0eSRuss Weight } 54bdf86d0eSRuss Weight 55bdf86d0eSRuss Weight ret = regmap_bulk_read(sec->m10bmc->regmap, reh_addr, 56bdf86d0eSRuss Weight hash, sha_num_bytes / stride); 57bdf86d0eSRuss Weight if (ret) { 58bdf86d0eSRuss Weight dev_err(dev, "failed to read root entry hash: %x cnt %x: %d\n", 59bdf86d0eSRuss Weight reh_addr, sha_num_bytes / stride, ret); 60bdf86d0eSRuss Weight return ret; 61bdf86d0eSRuss Weight } 62bdf86d0eSRuss Weight 63bdf86d0eSRuss Weight for (i = 0; i < sha_num_bytes; i++) 64bdf86d0eSRuss Weight cnt += sprintf(buf + cnt, "%02x", hash[i]); 65bdf86d0eSRuss Weight cnt += sprintf(buf + cnt, "\n"); 66bdf86d0eSRuss Weight 67bdf86d0eSRuss Weight return cnt; 68bdf86d0eSRuss Weight } 69bdf86d0eSRuss Weight 70bdf86d0eSRuss Weight #define DEVICE_ATTR_SEC_REH_RO(_name, _magic, _prog_addr, _reh_addr) \ 71bdf86d0eSRuss Weight static ssize_t _name##_root_entry_hash_show(struct device *dev, \ 72bdf86d0eSRuss Weight struct device_attribute *attr, \ 73bdf86d0eSRuss Weight char *buf) \ 74bdf86d0eSRuss Weight { return show_root_entry_hash(dev, _magic, _prog_addr, _reh_addr, buf); } \ 75bdf86d0eSRuss Weight static DEVICE_ATTR_RO(_name##_root_entry_hash) 76bdf86d0eSRuss Weight 77bdf86d0eSRuss Weight DEVICE_ATTR_SEC_REH_RO(bmc, BMC_PROG_MAGIC, BMC_PROG_ADDR, BMC_REH_ADDR); 78bdf86d0eSRuss Weight DEVICE_ATTR_SEC_REH_RO(sr, SR_PROG_MAGIC, SR_PROG_ADDR, SR_REH_ADDR); 79bdf86d0eSRuss Weight DEVICE_ATTR_SEC_REH_RO(pr, PR_PROG_MAGIC, PR_PROG_ADDR, PR_REH_ADDR); 80bdf86d0eSRuss Weight 81*154afa5cSRuss Weight #define FLASH_COUNT_SIZE 4096 /* count stored as inverted bit vector */ 82*154afa5cSRuss Weight 83*154afa5cSRuss Weight static ssize_t flash_count_show(struct device *dev, 84*154afa5cSRuss Weight struct device_attribute *attr, char *buf) 85*154afa5cSRuss Weight { 86*154afa5cSRuss Weight struct m10bmc_sec *sec = dev_get_drvdata(dev); 87*154afa5cSRuss Weight unsigned int stride, num_bits; 88*154afa5cSRuss Weight u8 *flash_buf; 89*154afa5cSRuss Weight int cnt, ret; 90*154afa5cSRuss Weight 91*154afa5cSRuss Weight stride = regmap_get_reg_stride(sec->m10bmc->regmap); 92*154afa5cSRuss Weight num_bits = FLASH_COUNT_SIZE * 8; 93*154afa5cSRuss Weight 94*154afa5cSRuss Weight flash_buf = kmalloc(FLASH_COUNT_SIZE, GFP_KERNEL); 95*154afa5cSRuss Weight if (!flash_buf) 96*154afa5cSRuss Weight return -ENOMEM; 97*154afa5cSRuss Weight 98*154afa5cSRuss Weight if (FLASH_COUNT_SIZE % stride) { 99*154afa5cSRuss Weight dev_err(sec->dev, 100*154afa5cSRuss Weight "FLASH_COUNT_SIZE (0x%x) not aligned to stride (0x%x)\n", 101*154afa5cSRuss Weight FLASH_COUNT_SIZE, stride); 102*154afa5cSRuss Weight WARN_ON_ONCE(1); 103*154afa5cSRuss Weight return -EINVAL; 104*154afa5cSRuss Weight } 105*154afa5cSRuss Weight 106*154afa5cSRuss Weight ret = regmap_bulk_read(sec->m10bmc->regmap, STAGING_FLASH_COUNT, 107*154afa5cSRuss Weight flash_buf, FLASH_COUNT_SIZE / stride); 108*154afa5cSRuss Weight if (ret) { 109*154afa5cSRuss Weight dev_err(sec->dev, 110*154afa5cSRuss Weight "failed to read flash count: %x cnt %x: %d\n", 111*154afa5cSRuss Weight STAGING_FLASH_COUNT, FLASH_COUNT_SIZE / stride, ret); 112*154afa5cSRuss Weight goto exit_free; 113*154afa5cSRuss Weight } 114*154afa5cSRuss Weight cnt = num_bits - bitmap_weight((unsigned long *)flash_buf, num_bits); 115*154afa5cSRuss Weight 116*154afa5cSRuss Weight exit_free: 117*154afa5cSRuss Weight kfree(flash_buf); 118*154afa5cSRuss Weight 119*154afa5cSRuss Weight return ret ? : sysfs_emit(buf, "%u\n", cnt); 120*154afa5cSRuss Weight } 121*154afa5cSRuss Weight static DEVICE_ATTR_RO(flash_count); 122*154afa5cSRuss Weight 123bdf86d0eSRuss Weight static struct attribute *m10bmc_security_attrs[] = { 124*154afa5cSRuss Weight &dev_attr_flash_count.attr, 125bdf86d0eSRuss Weight &dev_attr_bmc_root_entry_hash.attr, 126bdf86d0eSRuss Weight &dev_attr_sr_root_entry_hash.attr, 127bdf86d0eSRuss Weight &dev_attr_pr_root_entry_hash.attr, 128bdf86d0eSRuss Weight NULL, 129bdf86d0eSRuss Weight }; 130bdf86d0eSRuss Weight 131bdf86d0eSRuss Weight static struct attribute_group m10bmc_security_attr_group = { 132bdf86d0eSRuss Weight .name = "security", 133bdf86d0eSRuss Weight .attrs = m10bmc_security_attrs, 134bdf86d0eSRuss Weight }; 135bdf86d0eSRuss Weight 136bdf86d0eSRuss Weight static const struct attribute_group *m10bmc_sec_attr_groups[] = { 137bdf86d0eSRuss Weight &m10bmc_security_attr_group, 138bdf86d0eSRuss Weight NULL, 139bdf86d0eSRuss Weight }; 140bdf86d0eSRuss Weight 141bdf86d0eSRuss Weight #define SEC_UPDATE_LEN_MAX 32 142bdf86d0eSRuss Weight static int m10bmc_sec_probe(struct platform_device *pdev) 143bdf86d0eSRuss Weight { 144bdf86d0eSRuss Weight struct m10bmc_sec *sec; 145bdf86d0eSRuss Weight 146bdf86d0eSRuss Weight sec = devm_kzalloc(&pdev->dev, sizeof(*sec), GFP_KERNEL); 147bdf86d0eSRuss Weight if (!sec) 148bdf86d0eSRuss Weight return -ENOMEM; 149bdf86d0eSRuss Weight 150bdf86d0eSRuss Weight sec->dev = &pdev->dev; 151bdf86d0eSRuss Weight sec->m10bmc = dev_get_drvdata(pdev->dev.parent); 152bdf86d0eSRuss Weight dev_set_drvdata(&pdev->dev, sec); 153bdf86d0eSRuss Weight 154bdf86d0eSRuss Weight return 0; 155bdf86d0eSRuss Weight } 156bdf86d0eSRuss Weight 157bdf86d0eSRuss Weight static const struct platform_device_id intel_m10bmc_sec_ids[] = { 158bdf86d0eSRuss Weight { 159bdf86d0eSRuss Weight .name = "n3000bmc-sec-update", 160bdf86d0eSRuss Weight }, 161bdf86d0eSRuss Weight { } 162bdf86d0eSRuss Weight }; 163bdf86d0eSRuss Weight MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids); 164bdf86d0eSRuss Weight 165bdf86d0eSRuss Weight static struct platform_driver intel_m10bmc_sec_driver = { 166bdf86d0eSRuss Weight .probe = m10bmc_sec_probe, 167bdf86d0eSRuss Weight .driver = { 168bdf86d0eSRuss Weight .name = "intel-m10bmc-sec-update", 169bdf86d0eSRuss Weight .dev_groups = m10bmc_sec_attr_groups, 170bdf86d0eSRuss Weight }, 171bdf86d0eSRuss Weight .id_table = intel_m10bmc_sec_ids, 172bdf86d0eSRuss Weight }; 173bdf86d0eSRuss Weight module_platform_driver(intel_m10bmc_sec_driver); 174bdf86d0eSRuss Weight 175bdf86d0eSRuss Weight MODULE_AUTHOR("Intel Corporation"); 176bdf86d0eSRuss Weight MODULE_DESCRIPTION("Intel MAX10 BMC Secure Update"); 177bdf86d0eSRuss Weight MODULE_LICENSE("GPL"); 178