1a05bd1b4SWei Huang /* SPDX-License-Identifier: BSD-3-Clause
2a05bd1b4SWei Huang * Copyright(c) 2020 Intel Corporation
3a05bd1b4SWei Huang */
4a05bd1b4SWei Huang
5a05bd1b4SWei Huang #include <fcntl.h>
6a05bd1b4SWei Huang #include <signal.h>
7a05bd1b4SWei Huang #include <unistd.h>
8a05bd1b4SWei Huang #include "ifpga_sec_mgr.h"
9a05bd1b4SWei Huang
10a05bd1b4SWei Huang static struct ifpga_sec_mgr *sec_mgr;
11a05bd1b4SWei Huang
set_rsu_control(struct ifpga_sec_mgr * smgr,uint32_t ctrl)12a05bd1b4SWei Huang static void set_rsu_control(struct ifpga_sec_mgr *smgr, uint32_t ctrl)
13a05bd1b4SWei Huang {
14a05bd1b4SWei Huang if (smgr && smgr->rsu_control)
15a05bd1b4SWei Huang *smgr->rsu_control = ctrl;
16a05bd1b4SWei Huang }
17a05bd1b4SWei Huang
get_rsu_control(struct ifpga_sec_mgr * smgr)18a05bd1b4SWei Huang static uint32_t get_rsu_control(struct ifpga_sec_mgr *smgr)
19a05bd1b4SWei Huang {
20a05bd1b4SWei Huang if (smgr && smgr->rsu_control)
21a05bd1b4SWei Huang return *smgr->rsu_control;
22a05bd1b4SWei Huang return 0;
23a05bd1b4SWei Huang }
24a05bd1b4SWei Huang
set_rsu_status(struct ifpga_sec_mgr * smgr,uint32_t status,uint32_t progress)25a05bd1b4SWei Huang static void set_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t status,
26a05bd1b4SWei Huang uint32_t progress)
27a05bd1b4SWei Huang {
28a05bd1b4SWei Huang if (smgr && smgr->rsu_status)
29a05bd1b4SWei Huang *smgr->rsu_status = IFPGA_RSU_STATUS(status, progress);
30a05bd1b4SWei Huang }
31a05bd1b4SWei Huang
get_rsu_status(struct ifpga_sec_mgr * smgr,uint32_t * status,uint32_t * progress)32a05bd1b4SWei Huang static void get_rsu_status(struct ifpga_sec_mgr *smgr, uint32_t *status,
33a05bd1b4SWei Huang uint32_t *progress)
34a05bd1b4SWei Huang {
35a05bd1b4SWei Huang if (smgr && smgr->rsu_status) {
36a05bd1b4SWei Huang if (status)
37a05bd1b4SWei Huang *status = IFPGA_RSU_GET_STAT(*smgr->rsu_status);
38a05bd1b4SWei Huang if (progress)
39a05bd1b4SWei Huang *progress = IFPGA_RSU_GET_PROG(*smgr->rsu_status);
40a05bd1b4SWei Huang }
41a05bd1b4SWei Huang }
42a05bd1b4SWei Huang
sig_handler(int sig,siginfo_t * info,void * data)43a05bd1b4SWei Huang static void sig_handler(int sig, siginfo_t *info, void *data)
44a05bd1b4SWei Huang {
45a05bd1b4SWei Huang (void)(info);
46a05bd1b4SWei Huang (void)(data);
47a05bd1b4SWei Huang
48a05bd1b4SWei Huang switch (sig) {
49a05bd1b4SWei Huang case SIGINT:
50a05bd1b4SWei Huang if (sec_mgr) {
51a05bd1b4SWei Huang dev_info(sec_mgr, "Interrupt secure flash update"
52a05bd1b4SWei Huang " by keyboard\n");
53a05bd1b4SWei Huang set_rsu_control(sec_mgr, IFPGA_RSU_ABORT);
54a05bd1b4SWei Huang }
55a05bd1b4SWei Huang break;
56a05bd1b4SWei Huang default:
57a05bd1b4SWei Huang break;
58a05bd1b4SWei Huang }
59a05bd1b4SWei Huang }
60a05bd1b4SWei Huang
log_time(time_t t,const char * msg)61a05bd1b4SWei Huang static void log_time(time_t t, const char *msg)
62a05bd1b4SWei Huang {
63a05bd1b4SWei Huang uint32_t h = 0;
64a05bd1b4SWei Huang uint32_t m = 0;
65a05bd1b4SWei Huang uint32_t s = 0;
66a05bd1b4SWei Huang
67a05bd1b4SWei Huang if (t < 60) {
68a05bd1b4SWei Huang s = (uint32_t)t;
69a05bd1b4SWei Huang } else if (t < 3600) {
70a05bd1b4SWei Huang s = (uint32_t)(t % 60);
71a05bd1b4SWei Huang m = (uint32_t)(t / 60);
72a05bd1b4SWei Huang } else {
73a05bd1b4SWei Huang s = (uint32_t)(t % 60);
74a05bd1b4SWei Huang m = (uint32_t)((t % 3600) / 60);
75a05bd1b4SWei Huang h = (uint32_t)(t / 3600);
76a05bd1b4SWei Huang }
77a05bd1b4SWei Huang printf("%s - %02u:%02u:%02u\n", msg, h, m, s);
78a05bd1b4SWei Huang }
79a05bd1b4SWei Huang
start_flash_update(struct ifpga_sec_mgr * smgr)80a05bd1b4SWei Huang static int start_flash_update(struct ifpga_sec_mgr *smgr)
81a05bd1b4SWei Huang {
82a05bd1b4SWei Huang if (!smgr)
83a05bd1b4SWei Huang return -ENODEV;
84a05bd1b4SWei Huang
85a05bd1b4SWei Huang if (!smgr->ops || !smgr->ops->prepare)
86a05bd1b4SWei Huang return -EINVAL;
87a05bd1b4SWei Huang
88a05bd1b4SWei Huang return smgr->ops->prepare(smgr);
89a05bd1b4SWei Huang }
90a05bd1b4SWei Huang
write_flash_image(struct ifpga_sec_mgr * smgr,const char * image,uint32_t offset)91a05bd1b4SWei Huang static int write_flash_image(struct ifpga_sec_mgr *smgr, const char *image,
92a05bd1b4SWei Huang uint32_t offset)
93a05bd1b4SWei Huang {
94a05bd1b4SWei Huang void *buf = NULL;
95a05bd1b4SWei Huang int retry = 0;
96a05bd1b4SWei Huang uint32_t length = 0;
97a05bd1b4SWei Huang uint32_t to_transfer = 0;
98a05bd1b4SWei Huang uint32_t one_percent = 0;
99a05bd1b4SWei Huang uint32_t prog = 0;
100a05bd1b4SWei Huang uint32_t old_prog = -1;
101a05bd1b4SWei Huang ssize_t read_size = 0;
102a05bd1b4SWei Huang int fd = -1;
103a05bd1b4SWei Huang int ret = 0;
104a05bd1b4SWei Huang
105a05bd1b4SWei Huang if (!smgr)
106a05bd1b4SWei Huang return -ENODEV;
107a05bd1b4SWei Huang
108a05bd1b4SWei Huang if (!smgr->ops || !smgr->ops->write_blk)
109a05bd1b4SWei Huang return -EINVAL;
110a05bd1b4SWei Huang
111a05bd1b4SWei Huang fd = open(image, O_RDONLY);
112a05bd1b4SWei Huang if (fd < 0) {
113a05bd1b4SWei Huang dev_err(smgr,
114a05bd1b4SWei Huang "Failed to open \'%s\' for RD [e:%s]\n",
115a05bd1b4SWei Huang image, strerror(errno));
116a05bd1b4SWei Huang return -EIO;
117a05bd1b4SWei Huang }
118a05bd1b4SWei Huang
119a05bd1b4SWei Huang buf = malloc(IFPGA_RSU_DATA_BLK_SIZE);
120a05bd1b4SWei Huang if (!buf) {
121a05bd1b4SWei Huang dev_err(smgr, "Failed to allocate memory for flash update\n");
122a05bd1b4SWei Huang close(fd);
123a05bd1b4SWei Huang return -ENOMEM;
124a05bd1b4SWei Huang }
125a05bd1b4SWei Huang
126a05bd1b4SWei Huang length = smgr->rsu_length;
127a05bd1b4SWei Huang one_percent = length / 100;
128a05bd1b4SWei Huang do {
129a05bd1b4SWei Huang to_transfer = (length > IFPGA_RSU_DATA_BLK_SIZE) ?
130a05bd1b4SWei Huang IFPGA_RSU_DATA_BLK_SIZE : length;
131226ecdeaSWei Huang if (lseek(fd, offset, SEEK_SET) < 0) {
132226ecdeaSWei Huang dev_err(smgr, "Failed to seek in \'%s\' [e:%s]\n",
133226ecdeaSWei Huang image, strerror(errno));
134226ecdeaSWei Huang ret = -EIO;
135226ecdeaSWei Huang goto end;
136226ecdeaSWei Huang }
137a05bd1b4SWei Huang read_size = read(fd, buf, to_transfer);
138a05bd1b4SWei Huang if (read_size < 0) {
139a05bd1b4SWei Huang dev_err(smgr, "Failed to read from \'%s\' [e:%s]\n",
140a05bd1b4SWei Huang image, strerror(errno));
141a05bd1b4SWei Huang ret = -EIO;
142a05bd1b4SWei Huang goto end;
143a05bd1b4SWei Huang }
144a05bd1b4SWei Huang if ((uint32_t)read_size != to_transfer) {
145a05bd1b4SWei Huang dev_err(smgr,
146a05bd1b4SWei Huang "Read length %zd is not expected [e:%u]\n",
147a05bd1b4SWei Huang read_size, to_transfer);
148a05bd1b4SWei Huang ret = -EIO;
149a05bd1b4SWei Huang goto end;
150a05bd1b4SWei Huang }
151a05bd1b4SWei Huang
152a05bd1b4SWei Huang retry = 0;
153a05bd1b4SWei Huang do {
154a05bd1b4SWei Huang if (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {
155a05bd1b4SWei Huang ret = -EAGAIN;
156a05bd1b4SWei Huang goto end;
157a05bd1b4SWei Huang }
158a05bd1b4SWei Huang ret = smgr->ops->write_blk(smgr, buf, offset,
159a05bd1b4SWei Huang to_transfer);
160a05bd1b4SWei Huang if (ret == 0)
161a05bd1b4SWei Huang break;
162a05bd1b4SWei Huang sleep(1);
163a05bd1b4SWei Huang } while (++retry <= IFPGA_RSU_WRITE_RETRY);
164a05bd1b4SWei Huang if (retry > IFPGA_RSU_WRITE_RETRY) {
165a05bd1b4SWei Huang dev_err(smgr, "Failed to write to staging area 0x%x\n",
166a05bd1b4SWei Huang offset);
167a05bd1b4SWei Huang ret = -EAGAIN;
168a05bd1b4SWei Huang goto end;
169a05bd1b4SWei Huang }
170a05bd1b4SWei Huang
171a05bd1b4SWei Huang length -= to_transfer;
172a05bd1b4SWei Huang offset += to_transfer;
173a05bd1b4SWei Huang prog = offset / one_percent;
174a05bd1b4SWei Huang if (prog != old_prog) {
175a05bd1b4SWei Huang printf("\r%d%%", prog);
176a05bd1b4SWei Huang fflush(stdout);
177a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_READY, prog);
178a05bd1b4SWei Huang old_prog = prog;
179a05bd1b4SWei Huang }
180a05bd1b4SWei Huang } while (length > 0);
181a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_READY, 100);
182a05bd1b4SWei Huang printf("\n");
183a05bd1b4SWei Huang
184a05bd1b4SWei Huang end:
185a05bd1b4SWei Huang free(buf);
186a05bd1b4SWei Huang close(fd);
187a05bd1b4SWei Huang return ret;
188a05bd1b4SWei Huang }
189a05bd1b4SWei Huang
apply_flash_update(struct ifpga_sec_mgr * smgr)190a05bd1b4SWei Huang static int apply_flash_update(struct ifpga_sec_mgr *smgr)
191a05bd1b4SWei Huang {
192a05bd1b4SWei Huang uint32_t one_percent = 0;
193a05bd1b4SWei Huang uint32_t one_percent_time = 0;
194a05bd1b4SWei Huang uint32_t prog = 0;
195a05bd1b4SWei Huang uint32_t old_prog = -1;
196a05bd1b4SWei Huang uint32_t copy_time = 0;
197a05bd1b4SWei Huang int ret = 0;
198a05bd1b4SWei Huang
199a05bd1b4SWei Huang if (!smgr)
200a05bd1b4SWei Huang return -ENODEV;
201a05bd1b4SWei Huang
202a05bd1b4SWei Huang if (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)
203a05bd1b4SWei Huang return -EINVAL;
204a05bd1b4SWei Huang
205a05bd1b4SWei Huang if (smgr->ops->write_done(smgr) < 0) {
206a05bd1b4SWei Huang dev_err(smgr, "Failed to apply flash update\n");
207a05bd1b4SWei Huang return -EAGAIN;
208a05bd1b4SWei Huang }
209a05bd1b4SWei Huang
210a05bd1b4SWei Huang one_percent = (smgr->rsu_length + 99) / 100;
211a05bd1b4SWei Huang if (smgr->copy_speed == 0) /* avoid zero divide fault */
212a05bd1b4SWei Huang smgr->copy_speed = 1;
213a05bd1b4SWei Huang one_percent_time = (one_percent + smgr->copy_speed - 1) /
214a05bd1b4SWei Huang smgr->copy_speed;
215a05bd1b4SWei Huang if (one_percent_time == 0) /* avoid zero divide fault */
216a05bd1b4SWei Huang one_percent_time = 1;
217a05bd1b4SWei Huang
218a05bd1b4SWei Huang do {
219a05bd1b4SWei Huang ret = smgr->ops->check_complete(smgr);
220a05bd1b4SWei Huang if (ret != -EAGAIN)
221a05bd1b4SWei Huang break;
222a05bd1b4SWei Huang sleep(1);
223a05bd1b4SWei Huang copy_time += 1;
224a05bd1b4SWei Huang prog = copy_time / one_percent_time;
225a05bd1b4SWei Huang if (prog >= 100)
226a05bd1b4SWei Huang prog = 99;
227a05bd1b4SWei Huang if (prog != old_prog) {
228a05bd1b4SWei Huang printf("\r%d%%", prog);
229a05bd1b4SWei Huang fflush(stdout);
230a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
231a05bd1b4SWei Huang old_prog = prog;
232a05bd1b4SWei Huang }
233a05bd1b4SWei Huang } while (true);
234a05bd1b4SWei Huang
235a05bd1b4SWei Huang if (ret < 0) {
236a05bd1b4SWei Huang printf("\n");
237a05bd1b4SWei Huang dev_err(smgr, "Failed to complete secure flash update\n");
238a05bd1b4SWei Huang } else {
239a05bd1b4SWei Huang printf("\r100%%\n");
240a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
241a05bd1b4SWei Huang }
242a05bd1b4SWei Huang
243a05bd1b4SWei Huang return ret;
244a05bd1b4SWei Huang }
245a05bd1b4SWei Huang
secure_update_cancel(struct ifpga_sec_mgr * smgr)246a05bd1b4SWei Huang static int secure_update_cancel(struct ifpga_sec_mgr *smgr)
247a05bd1b4SWei Huang {
248a05bd1b4SWei Huang if (!smgr)
249a05bd1b4SWei Huang return -ENODEV;
250a05bd1b4SWei Huang
251a05bd1b4SWei Huang if (!smgr->ops || !smgr->ops->cancel)
252a05bd1b4SWei Huang return -EINVAL;
253a05bd1b4SWei Huang
254a05bd1b4SWei Huang return smgr->ops->cancel(smgr);
255a05bd1b4SWei Huang }
256a05bd1b4SWei Huang
secure_update_status(struct ifpga_sec_mgr * smgr,uint64_t * status)257a05bd1b4SWei Huang static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)
258a05bd1b4SWei Huang {
259a05bd1b4SWei Huang if (!smgr)
260a05bd1b4SWei Huang return -ENODEV;
261a05bd1b4SWei Huang
262a05bd1b4SWei Huang if (!smgr->ops || !smgr->ops->get_hw_errinfo)
263a05bd1b4SWei Huang return -EINVAL;
264a05bd1b4SWei Huang
265a05bd1b4SWei Huang if (status)
266a05bd1b4SWei Huang *status = smgr->ops->get_hw_errinfo(smgr);
267a05bd1b4SWei Huang
268a05bd1b4SWei Huang return 0;
269a05bd1b4SWei Huang }
270a05bd1b4SWei Huang
fpga_update_flash(struct ifpga_fme_hw * fme,const char * image,uint64_t * status)271a05bd1b4SWei Huang int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
272a05bd1b4SWei Huang uint64_t *status)
273a05bd1b4SWei Huang {
274a05bd1b4SWei Huang struct ifpga_hw *hw = NULL;
275a05bd1b4SWei Huang struct ifpga_sec_mgr *smgr = NULL;
276a05bd1b4SWei Huang uint32_t rsu_stat = 0;
277a05bd1b4SWei Huang int fd = -1;
278*bf95921aSWei Huang off_t len = 0;
279a05bd1b4SWei Huang struct sigaction old_sigint_action;
280a05bd1b4SWei Huang struct sigaction sa;
281a05bd1b4SWei Huang time_t start;
282a05bd1b4SWei Huang int ret = 0;
283a05bd1b4SWei Huang
284a05bd1b4SWei Huang if (!fme || !image || !status) {
285a05bd1b4SWei Huang dev_err(fme, "Input parameter of %s is invalid\n", __func__);
286a05bd1b4SWei Huang return -EINVAL;
287a05bd1b4SWei Huang }
288a05bd1b4SWei Huang
289a05bd1b4SWei Huang hw = (struct ifpga_hw *)fme->parent;
290a05bd1b4SWei Huang if (!hw) {
291a05bd1b4SWei Huang dev_err(fme, "Parent of FME not found\n");
292a05bd1b4SWei Huang return -ENODEV;
293a05bd1b4SWei Huang }
294a05bd1b4SWei Huang
295a05bd1b4SWei Huang smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
296a05bd1b4SWei Huang if (!smgr || !smgr->max10_dev) {
297a05bd1b4SWei Huang dev_err(smgr, "Security manager not initialized\n");
298a05bd1b4SWei Huang return -ENODEV;
299a05bd1b4SWei Huang }
300a05bd1b4SWei Huang
301a05bd1b4SWei Huang opae_adapter_lock(hw->adapter, -1);
302a05bd1b4SWei Huang get_rsu_status(smgr, &rsu_stat, NULL);
303a05bd1b4SWei Huang if (rsu_stat != IFPGA_RSU_IDLE) {
304a05bd1b4SWei Huang opae_adapter_unlock(hw->adapter);
305a05bd1b4SWei Huang if (rsu_stat == IFPGA_RSU_REBOOT)
306a05bd1b4SWei Huang dev_info(smgr, "Reboot is in progress\n");
307a05bd1b4SWei Huang else
308a05bd1b4SWei Huang dev_info(smgr, "Update is in progress\n");
309a05bd1b4SWei Huang return -EAGAIN;
310a05bd1b4SWei Huang }
311a05bd1b4SWei Huang set_rsu_control(smgr, 0);
312a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);
313a05bd1b4SWei Huang opae_adapter_unlock(hw->adapter);
314a05bd1b4SWei Huang
315a05bd1b4SWei Huang fd = open(image, O_RDONLY);
316a05bd1b4SWei Huang if (fd < 0) {
317a05bd1b4SWei Huang dev_err(smgr,
318a05bd1b4SWei Huang "Failed to open \'%s\' for RD [e:%s]\n",
319a05bd1b4SWei Huang image, strerror(errno));
320a05bd1b4SWei Huang return -EIO;
321a05bd1b4SWei Huang }
322*bf95921aSWei Huang len = lseek(fd, 0, SEEK_END);
323a05bd1b4SWei Huang close(fd);
324a05bd1b4SWei Huang
325*bf95921aSWei Huang if (len < 0) {
326*bf95921aSWei Huang dev_err(smgr,
327*bf95921aSWei Huang "Failed to get file length of \'%s\' [e:%s]\n",
328*bf95921aSWei Huang image, strerror(errno));
329*bf95921aSWei Huang return -EIO;
330*bf95921aSWei Huang }
331*bf95921aSWei Huang if (len == 0) {
332*bf95921aSWei Huang dev_err(smgr, "Length of file \'%s\' is invalid\n", image);
333*bf95921aSWei Huang return -EINVAL;
334*bf95921aSWei Huang }
335*bf95921aSWei Huang smgr->rsu_length = len;
336*bf95921aSWei Huang
337a05bd1b4SWei Huang if (smgr->max10_dev->staging_area_size < smgr->rsu_length) {
338a05bd1b4SWei Huang dev_err(dev, "Size of staging area is small than image length "
339a05bd1b4SWei Huang "[%u<%u]\n", smgr->max10_dev->staging_area_size,
340a05bd1b4SWei Huang smgr->rsu_length);
341a05bd1b4SWei Huang return -EINVAL;
342a05bd1b4SWei Huang }
343a05bd1b4SWei Huang
344a05bd1b4SWei Huang printf("Updating from file \'%s\' with size %u\n",
345a05bd1b4SWei Huang image, smgr->rsu_length);
346a05bd1b4SWei Huang
347a05bd1b4SWei Huang sec_mgr = smgr;
348a05bd1b4SWei Huang memset(&sa, 0, sizeof(struct sigaction));
349a05bd1b4SWei Huang sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
350a05bd1b4SWei Huang sa.sa_sigaction = sig_handler;
351a05bd1b4SWei Huang ret = sigaction(SIGINT, &sa, &old_sigint_action);
352a05bd1b4SWei Huang if (ret < 0) {
353a05bd1b4SWei Huang dev_warn(dev, "Failed to register signal handler"
354a05bd1b4SWei Huang " [e:%d]\n", ret);
355a05bd1b4SWei Huang sec_mgr = NULL;
356a05bd1b4SWei Huang }
357a05bd1b4SWei Huang
358a05bd1b4SWei Huang start = time(NULL);
359a05bd1b4SWei Huang log_time(time(NULL) - start, "Starting secure flash update");
360a05bd1b4SWei Huang ret = start_flash_update(smgr);
361a05bd1b4SWei Huang if (ret < 0)
362a05bd1b4SWei Huang goto end;
363a05bd1b4SWei Huang
364a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_READY, 0);
365a05bd1b4SWei Huang log_time(time(NULL) - start, "Writing to staging area");
366a05bd1b4SWei Huang ret = write_flash_image(smgr, image, 0);
367a05bd1b4SWei Huang if (ret < 0)
368a05bd1b4SWei Huang goto end;
369a05bd1b4SWei Huang
370a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
371a05bd1b4SWei Huang log_time(time(NULL) - start, "Applying secure flash update");
372a05bd1b4SWei Huang ret = apply_flash_update(smgr);
373a05bd1b4SWei Huang
374a05bd1b4SWei Huang end:
375a05bd1b4SWei Huang if (sec_mgr) {
376a05bd1b4SWei Huang sec_mgr = NULL;
377a05bd1b4SWei Huang if (sigaction(SIGINT, &old_sigint_action, NULL) < 0)
378a05bd1b4SWei Huang dev_err(smgr, "Failed to unregister signal handler\n");
379a05bd1b4SWei Huang }
380a05bd1b4SWei Huang
381a05bd1b4SWei Huang secure_update_status(smgr, status);
382a05bd1b4SWei Huang if (ret < 0) {
383a05bd1b4SWei Huang log_time(time(NULL) - start, "Secure flash update ERROR");
384a05bd1b4SWei Huang if (ret == -EAGAIN)
385a05bd1b4SWei Huang secure_update_cancel(smgr);
386a05bd1b4SWei Huang } else {
387a05bd1b4SWei Huang log_time(time(NULL) - start, "Secure flash update OK");
388a05bd1b4SWei Huang }
389a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
390a05bd1b4SWei Huang
391a05bd1b4SWei Huang return ret;
392a05bd1b4SWei Huang }
393a05bd1b4SWei Huang
fpga_stop_flash_update(struct ifpga_fme_hw * fme,int force)394a05bd1b4SWei Huang int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
395a05bd1b4SWei Huang {
396a05bd1b4SWei Huang struct ifpga_sec_mgr *smgr = NULL;
397a05bd1b4SWei Huang uint32_t status = 0;
398a05bd1b4SWei Huang int retry = IFPGA_RSU_CANCEL_RETRY;
399a05bd1b4SWei Huang int ret = 0;
400a05bd1b4SWei Huang
401a05bd1b4SWei Huang if (!fme) {
402a05bd1b4SWei Huang dev_err(fme, "Input parameter of %s is invalid\n", __func__);
403a05bd1b4SWei Huang return -EINVAL;
404a05bd1b4SWei Huang }
405a05bd1b4SWei Huang smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
406a05bd1b4SWei Huang
407a05bd1b4SWei Huang get_rsu_status(smgr, &status, NULL);
408a05bd1b4SWei Huang if (status != IFPGA_RSU_IDLE) {
409a05bd1b4SWei Huang dev_info(smgr, "Cancel secure flash update\n");
410a05bd1b4SWei Huang set_rsu_control(smgr, IFPGA_RSU_ABORT);
411a05bd1b4SWei Huang }
412a05bd1b4SWei Huang
413a05bd1b4SWei Huang if (force) {
414a05bd1b4SWei Huang sleep(2);
415a05bd1b4SWei Huang do {
416a05bd1b4SWei Huang get_rsu_status(smgr, &status, NULL);
417a05bd1b4SWei Huang if (status == IFPGA_RSU_IDLE)
418a05bd1b4SWei Huang break;
419a05bd1b4SWei Huang if (secure_update_cancel(smgr) == 0)
420a05bd1b4SWei Huang set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
421a05bd1b4SWei Huang sleep(1);
422a05bd1b4SWei Huang } while (--retry > 0);
423a05bd1b4SWei Huang if (retry <= 0) {
424a05bd1b4SWei Huang dev_err(smgr, "Failed to stop flash update\n");
425a05bd1b4SWei Huang ret = -EAGAIN;
426a05bd1b4SWei Huang }
427a05bd1b4SWei Huang }
428a05bd1b4SWei Huang
429a05bd1b4SWei Huang return ret;
430a05bd1b4SWei Huang }
431a05bd1b4SWei Huang
fpga_reload(struct ifpga_fme_hw * fme,int type,int page)432a05bd1b4SWei Huang int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
433a05bd1b4SWei Huang {
434a05bd1b4SWei Huang struct ifpga_sec_mgr *smgr = NULL;
435a05bd1b4SWei Huang
436a05bd1b4SWei Huang if (!fme) {
437a05bd1b4SWei Huang dev_err(fme, "Input parameter of %s is invalid\n", __func__);
438a05bd1b4SWei Huang return -EINVAL;
439a05bd1b4SWei Huang }
440a05bd1b4SWei Huang smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
441a05bd1b4SWei Huang
442a05bd1b4SWei Huang if (!smgr || !smgr->ops || !smgr->ops->reload)
443a05bd1b4SWei Huang return -EINVAL;
444a05bd1b4SWei Huang
445a05bd1b4SWei Huang return smgr->ops->reload(smgr, type, page);
446a05bd1b4SWei Huang }
447