Skip to content

Commit ccc3008

Browse files
Figo-zhangRuss Weight
authored andcommitted
fpga: m10bmc-sec: support power on image
This patch supports that selects image to be configured of the FPGA during next boot.
1 parent 66fd123 commit ccc3008

5 files changed

Lines changed: 219 additions & 2 deletions

File tree

Documentation/ABI/testing/sysfs-driver-intel-m10-bmc-secure

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,21 @@ Contact: Russ Weight <russell.h.weight@intel.com>
5959
Description: Read only. Returns number of times the secure update
6060
staging area has been flashed.
6161
Format: "%u".
62+
63+
What:
64+
/sys/bus/platform/devices/n3000bmc-secure.*.auto/available_power_on_images
65+
Date: January 2021
66+
KernelVersion: 5.12
67+
Contact: Tianfei zhang <tianfei.zhang@intel.com>
68+
Description: Read-only. This file returns a space separated list of
69+
key words that may be written into the power_on_image file
70+
described below. These keywords decribe an default image on
71+
next boot-up.
72+
73+
What: /sys/bus/platform/devices/n3000bmc-secure.*.auto/power_on_image
74+
Date: January 2021
75+
KernelVersion: 5.12
76+
Contact: Tianfei zhang <tianfei.zhang@intel.com>
77+
Description: Read/Write. A key word may be written to this file to
78+
trigger the image which will be configured of the FPGA during next boot.
79+
Read this entry will return which image has been configured.

drivers/fpga/fpga-sec-mgr.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,6 @@ struct fpga_sec_mgr_devres {
2323

2424
#define WRITE_BLOCK_SIZE 0x4000 /* Update remaining_size every 0x4000 bytes */
2525

26-
#define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
27-
2826
static void update_progress(struct fpga_sec_mgr *smgr,
2927
enum fpga_sec_prog new_progress)
3028
{

drivers/fpga/intel-m10-bmc-secure.c

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ struct m10bmc_sec {
2020
enum fpga_sec_type type;
2121
};
2222

23+
static const struct image_load *curr_poc;
24+
2325
/* Root Entry Hash (REH) support */
2426
#define REH_SHA256_SIZE 32
2527
#define REH_SHA384_SIZE 48
@@ -150,6 +152,177 @@ static ssize_t flash_count_show(struct device *dev,
150152
}
151153
static DEVICE_ATTR_RO(flash_count);
152154

155+
static ssize_t
156+
available_power_on_images_show(struct device *dev,
157+
struct device_attribute *attr, char *buf)
158+
{
159+
struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
160+
const struct image_load *hndlr;
161+
ssize_t count = 0;
162+
163+
for (hndlr = smgr->sops->power_on_image; hndlr->name; hndlr++) {
164+
count += scnprintf(buf + count, PAGE_SIZE - count,
165+
"%s ", hndlr->name);
166+
}
167+
168+
buf[count - 1] = '\n';
169+
170+
return count;
171+
}
172+
static DEVICE_ATTR_RO(available_power_on_images);
173+
174+
static ssize_t
175+
power_on_image_show(struct device *dev,
176+
struct device_attribute *attr, char *buf)
177+
{
178+
ssize_t count = 0;
179+
180+
if (!curr_poc)
181+
return -EINVAL;
182+
183+
count = scnprintf(buf + count, PAGE_SIZE - count,
184+
"%s ", curr_poc->name);
185+
buf[count - 1] = '\n';
186+
187+
return count;
188+
}
189+
190+
static ssize_t
191+
power_on_image_store(struct device *dev,
192+
struct device_attribute *attr, const char *buf, size_t count)
193+
{
194+
struct fpga_sec_mgr *smgr = to_sec_mgr(dev);
195+
const struct image_load *hndlr;
196+
int ret = -EINVAL;
197+
198+
for (hndlr = smgr->sops->power_on_image; hndlr->name; hndlr++) {
199+
if (sysfs_streq(buf, hndlr->name)) {
200+
ret = hndlr->load_image(smgr);
201+
curr_poc = hndlr;
202+
break;
203+
}
204+
}
205+
206+
return ret ? : count;
207+
}
208+
static DEVICE_ATTR_RW(power_on_image);
209+
210+
static int pmci_sec_power_on_image(struct fpga_sec_mgr *smgr, unsigned char boot_image)
211+
{
212+
struct m10bmc_sec *sec = smgr->priv;
213+
u32 poc = 0;
214+
int ret;
215+
216+
if (boot_image > FPGA_POC_FACTORY_U2) {
217+
dev_err(sec->dev, "%s invalid boot image = %d\n", __func__, boot_image);
218+
return -EINVAL;
219+
}
220+
221+
switch (boot_image) {
222+
case FPGA_POC_USER_IMAGE_1:
223+
poc |= FIELD_PREP(PMCI_USER_IMAGE_PAGE, POC_USER_IMAGE_1);
224+
break;
225+
case FPGA_POC_USER_IMAGE_2:
226+
poc |= FIELD_PREP(PMCI_USER_IMAGE_PAGE, POC_USER_IMAGE_2);
227+
break;
228+
case FPGA_POC_FACTORY_U1:
229+
poc |= PMCI_FACTORY_IMAGE_PAGE | FIELD_PREP(PMCI_USER_IMAGE_PAGE,
230+
POC_USER_IMAGE_1);
231+
break;
232+
case FPGA_POC_FACTORY_U2:
233+
poc |= PMCI_FACTORY_IMAGE_PAGE | FIELD_PREP(PMCI_USER_IMAGE_PAGE,
234+
POC_USER_IMAGE_2);
235+
break;
236+
default:
237+
return -EINVAL;
238+
}
239+
240+
ret = m10bmc_sys_update_bits(sec->m10bmc,
241+
m10bmc_base(sec->m10bmc) + PMCI_M10BMC_FPGA_POC,
242+
PMCI_FPGA_POC |
243+
PMCI_USER_IMAGE_PAGE |
244+
PMCI_FACTORY_IMAGE_PAGE,
245+
poc | PMCI_FPGA_POC);
246+
if (ret)
247+
return ret;
248+
249+
ret = regmap_read_poll_timeout(sec->m10bmc->regmap,
250+
m10bmc_base(sec->m10bmc) + PMCI_M10BMC_FPGA_POC,
251+
poc,
252+
(!(poc & PMCI_FPGA_POC)),
253+
NIOS_HANDSHAKE_INTERVAL_US,
254+
NIOS_HANDSHAKE_TIMEOUT_US);
255+
if (ret || (FIELD_GET(PMCI_NIOS_STATUS, poc) != NIOS_STATUS_SUCCESS))
256+
return -EIO;
257+
258+
return 0;
259+
}
260+
261+
static int pmci_sec_power_on_image_0(struct fpga_sec_mgr *smgr)
262+
{
263+
return pmci_sec_power_on_image(smgr, FPGA_POC_USER_IMAGE_1);
264+
}
265+
266+
static int pmci_sec_power_on_image_1(struct fpga_sec_mgr *smgr)
267+
{
268+
return pmci_sec_power_on_image(smgr, FPGA_POC_USER_IMAGE_2);
269+
}
270+
271+
static int pmci_sec_power_on_image_2(struct fpga_sec_mgr *smgr)
272+
{
273+
return pmci_sec_power_on_image(smgr, FPGA_POC_FACTORY_U1);
274+
}
275+
276+
static int pmci_sec_power_on_image_3(struct fpga_sec_mgr *smgr)
277+
{
278+
return pmci_sec_power_on_image(smgr, FPGA_POC_FACTORY_U2);
279+
}
280+
281+
static struct image_load pmci_power_on_image_hndlrs[] = {
282+
{
283+
.name = "fpga_user1",
284+
.load_image = pmci_sec_power_on_image_0,
285+
},
286+
{
287+
.name = "fpga_user2",
288+
.load_image = pmci_sec_power_on_image_1,
289+
},
290+
{
291+
.name = "fpga_factory",
292+
.load_image = pmci_sec_power_on_image_2,
293+
},
294+
{
295+
.name = "fpga_factory_option1",
296+
.load_image = pmci_sec_power_on_image_3,
297+
},
298+
{}
299+
};
300+
301+
static umode_t
302+
m10bmc_image_visible(struct kobject *kobj,
303+
struct attribute *attr, int n)
304+
{
305+
struct fpga_sec_mgr *smgr = to_sec_mgr(kobj_to_dev(kobj));
306+
struct m10bmc_sec *sec = smgr->priv;
307+
enum fpga_sec_type type = sec->m10bmc->type;
308+
309+
if (type == PMCI_SEC)
310+
return attr->mode;
311+
312+
return 0;
313+
}
314+
315+
static struct attribute *m10bmc_image_attrs[] = {
316+
&dev_attr_power_on_image.attr,
317+
&dev_attr_available_power_on_images.attr,
318+
NULL,
319+
};
320+
321+
static struct attribute_group m10bmc_image_attr_group = {
322+
.attrs = m10bmc_image_attrs,
323+
.is_visible = m10bmc_image_visible,
324+
};
325+
153326
static struct attribute *m10bmc_security_attrs[] = {
154327
&dev_attr_flash_count.attr,
155328
&dev_attr_bmc_root_entry_hash.attr,
@@ -168,6 +341,7 @@ static struct attribute_group m10bmc_security_attr_group = {
168341

169342
static const struct attribute_group *m10bmc_sec_attr_groups[] = {
170343
&m10bmc_security_attr_group,
344+
&m10bmc_image_attr_group,
171345
NULL,
172346
};
173347

@@ -922,6 +1096,7 @@ m10bmc_sops_create(struct device *dev, enum fpga_sec_type type)
9221096
if (type == PMCI_SEC) {
9231097
sops->write_blk = pmci_sec_write_blk;
9241098
sops->image_load = pmci_image_load_hndlrs;
1099+
sops->power_on_image = pmci_power_on_image_hndlrs;
9251100
} else {
9261101
sops->write_blk = m10bmc_sec_write_blk;
9271102
}

include/linux/fpga/fpga-sec-mgr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ struct image_load {
6464
* { } member terminated. These structures describe
6565
* image load triggers for BMC, FPGA, or firmware
6666
* images.
67+
* @power_on_image: pointer to array of image_load structures,
68+
* { } member terminated. These structures describe
69+
* image setting which be configured of the FPGA during
70+
* next boot.
6771
*/
6872
struct fpga_sec_mgr_ops {
6973
enum fpga_sec_err (*prepare)(struct fpga_sec_mgr *smgr);
@@ -74,6 +78,7 @@ struct fpga_sec_mgr_ops {
7478
void (*cleanup)(struct fpga_sec_mgr *smgr);
7579
u64 (*get_hw_errinfo)(struct fpga_sec_mgr *smgr);
7680
struct image_load *image_load; /* terminated with { } member */
81+
struct image_load *power_on_image; /* terminated with { } member */
7782
};
7883

7984
/* Update progress codes */
@@ -105,6 +110,8 @@ struct fpga_sec_mgr {
105110
void *priv;
106111
};
107112

113+
#define to_sec_mgr(d) container_of(d, struct fpga_sec_mgr, dev)
114+
108115
struct fpga_sec_mgr *
109116
fpga_sec_mgr_create(struct device *dev, const char *name,
110117
const struct fpga_sec_mgr_ops *sops, void *priv);

include/linux/mfd/intel-m10-bmc.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ enum m10bmc_type {
201201
#define PMCI_MAX10_REBOOT_REQ BIT(0)
202202
#define PMCI_MAX10_REBOOT_PAGE BIT(1)
203203

204+
#define PMCI_M10BMC_FPGA_POC 0xb0
205+
#define PMCI_FPGA_POC BIT(0)
206+
#define PMCI_NIOS_REQ_CLEAR BIT(1)
207+
#define PMCI_NIOS_STATUS GENMASK(5, 4)
208+
#define NIOS_STATUS_IDLE 0
209+
#define NIOS_STATUS_SUCCESS 1
210+
#define NIOS_STATUS_FAIL 2
211+
#define PMCI_USER_IMAGE_PAGE GENMASK(10, 8)
212+
#define POC_USER_IMAGE_1 1
213+
#define POC_USER_IMAGE_2 2
214+
#define PMCI_FACTORY_IMAGE_PAGE BIT(31)
215+
204216
#define PMCI_M10BMC_FPGA_RECONF 0xb8
205217
#define PMCI_FPGA_RECONF_PAGE GENMASK(22, 20)
206218
#define PMCI_FPGA_RP_LOAD BIT(23)
@@ -209,6 +221,13 @@ enum m10bmc_type {
209221
#define doorbell_reg(m10bmc) ((m10bmc)->csr->doorbell)
210222
#define auth_result_reg(m10bmc) ((m10bmc)->csr->auth_result)
211223

224+
enum m10bmc_fpga_poc {
225+
FPGA_POC_USER_IMAGE_1,
226+
FPGA_POC_USER_IMAGE_2,
227+
FPGA_POC_FACTORY_U1,
228+
FPGA_POC_FACTORY_U2
229+
};
230+
212231
enum m10bmc_fw_state {
213232
M10BMC_FW_STATE_NORMAL,
214233
M10BMC_FW_STATE_SEC_UPDATE,

0 commit comments

Comments
 (0)