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