xref: /linux/drivers/fpga/intel-m10-bmc-sec-update.c (revision 154afa5c31cd2de5e6c2c4f35eee390993ee345a)
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