raw/ifpga/base: check file length
[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                 if (lseek(fd, offset, SEEK_SET) < 0) {
132                         dev_err(smgr, "Failed to seek in \'%s\' [e:%s]\n",
133                                 image, strerror(errno));
134                         ret = -EIO;
135                         goto end;
136                 }
137                 read_size = read(fd, buf, to_transfer);
138                 if (read_size < 0) {
139                         dev_err(smgr, "Failed to read from \'%s\' [e:%s]\n",
140                                 image, strerror(errno));
141                         ret = -EIO;
142                         goto end;
143                 }
144                 if ((uint32_t)read_size != to_transfer) {
145                         dev_err(smgr,
146                                 "Read length %zd is not expected [e:%u]\n",
147                                 read_size, to_transfer);
148                         ret = -EIO;
149                         goto end;
150                 }
151
152                 retry = 0;
153                 do {
154                         if (get_rsu_control(smgr) == IFPGA_RSU_ABORT) {
155                                 ret = -EAGAIN;
156                                 goto end;
157                         }
158                         ret = smgr->ops->write_blk(smgr, buf, offset,
159                                 to_transfer);
160                         if (ret == 0)
161                                 break;
162                         sleep(1);
163                 } while (++retry <= IFPGA_RSU_WRITE_RETRY);
164                 if (retry > IFPGA_RSU_WRITE_RETRY) {
165                         dev_err(smgr, "Failed to write to staging area 0x%x\n",
166                                 offset);
167                         ret = -EAGAIN;
168                         goto end;
169                 }
170
171                 length -= to_transfer;
172                 offset += to_transfer;
173                 prog = offset / one_percent;
174                 if (prog != old_prog) {
175                         printf("\r%d%%", prog);
176                         fflush(stdout);
177                         set_rsu_status(smgr, IFPGA_RSU_READY, prog);
178                         old_prog = prog;
179                 }
180         } while (length > 0);
181         set_rsu_status(smgr, IFPGA_RSU_READY, 100);
182         printf("\n");
183
184 end:
185         free(buf);
186         close(fd);
187         return ret;
188 }
189
190 static int apply_flash_update(struct ifpga_sec_mgr *smgr)
191 {
192         uint32_t one_percent = 0;
193         uint32_t one_percent_time = 0;
194         uint32_t prog = 0;
195         uint32_t old_prog = -1;
196         uint32_t copy_time = 0;
197         int ret = 0;
198
199         if (!smgr)
200                 return -ENODEV;
201
202         if (!smgr->ops || !smgr->ops->write_done || !smgr->ops->check_complete)
203                 return -EINVAL;
204
205         if (smgr->ops->write_done(smgr) < 0) {
206                 dev_err(smgr, "Failed to apply flash update\n");
207                 return -EAGAIN;
208         }
209
210         one_percent = (smgr->rsu_length + 99) / 100;
211         if (smgr->copy_speed == 0)   /* avoid zero divide fault */
212                 smgr->copy_speed = 1;
213         one_percent_time = (one_percent + smgr->copy_speed - 1) /
214                 smgr->copy_speed;
215         if (one_percent_time == 0)   /* avoid zero divide fault */
216                 one_percent_time = 1;
217
218         do {
219                 ret = smgr->ops->check_complete(smgr);
220                 if (ret != -EAGAIN)
221                         break;
222                 sleep(1);
223                 copy_time += 1;
224                 prog = copy_time / one_percent_time;
225                 if (prog >= 100)
226                         prog = 99;
227                 if (prog != old_prog) {
228                         printf("\r%d%%", prog);
229                         fflush(stdout);
230                         set_rsu_status(smgr, IFPGA_RSU_COPYING, prog);
231                         old_prog = prog;
232                 }
233         } while (true);
234
235         if (ret < 0) {
236                 printf("\n");
237                 dev_err(smgr, "Failed to complete secure flash update\n");
238         } else {
239                 printf("\r100%%\n");
240                 set_rsu_status(smgr, IFPGA_RSU_COPYING, 100);
241         }
242
243         return ret;
244 }
245
246 static int secure_update_cancel(struct ifpga_sec_mgr *smgr)
247 {
248         if (!smgr)
249                 return -ENODEV;
250
251         if (!smgr->ops || !smgr->ops->cancel)
252                 return -EINVAL;
253
254         return smgr->ops->cancel(smgr);
255 }
256
257 static int secure_update_status(struct ifpga_sec_mgr *smgr, uint64_t *status)
258 {
259         if (!smgr)
260                 return -ENODEV;
261
262         if (!smgr->ops || !smgr->ops->get_hw_errinfo)
263                 return -EINVAL;
264
265         if (status)
266                 *status = smgr->ops->get_hw_errinfo(smgr);
267
268         return 0;
269 }
270
271 int fpga_update_flash(struct ifpga_fme_hw *fme, const char *image,
272         uint64_t *status)
273 {
274         struct ifpga_hw *hw = NULL;
275         struct ifpga_sec_mgr *smgr = NULL;
276         uint32_t rsu_stat = 0;
277         int fd = -1;
278         off_t len = 0;
279         struct sigaction old_sigint_action;
280         struct sigaction sa;
281         time_t start;
282         int ret = 0;
283
284         if (!fme || !image || !status) {
285                 dev_err(fme, "Input parameter of %s is invalid\n", __func__);
286                 return -EINVAL;
287         }
288
289         hw = (struct ifpga_hw *)fme->parent;
290         if (!hw) {
291                 dev_err(fme, "Parent of FME not found\n");
292                 return -ENODEV;
293         }
294
295         smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
296         if (!smgr || !smgr->max10_dev) {
297                 dev_err(smgr, "Security manager not initialized\n");
298                 return -ENODEV;
299         }
300
301         opae_adapter_lock(hw->adapter, -1);
302         get_rsu_status(smgr, &rsu_stat, NULL);
303         if (rsu_stat != IFPGA_RSU_IDLE) {
304                 opae_adapter_unlock(hw->adapter);
305                 if (rsu_stat == IFPGA_RSU_REBOOT)
306                         dev_info(smgr, "Reboot is in progress\n");
307                 else
308                         dev_info(smgr, "Update is in progress\n");
309                 return -EAGAIN;
310         }
311         set_rsu_control(smgr, 0);
312         set_rsu_status(smgr, IFPGA_RSU_PREPARE, 0);
313         opae_adapter_unlock(hw->adapter);
314
315         fd = open(image, O_RDONLY);
316         if (fd < 0) {
317                 dev_err(smgr,
318                         "Failed to open \'%s\' for RD [e:%s]\n",
319                         image, strerror(errno));
320                 return -EIO;
321         }
322         len = lseek(fd, 0, SEEK_END);
323         close(fd);
324
325         if (len < 0) {
326                 dev_err(smgr,
327                         "Failed to get file length of \'%s\' [e:%s]\n",
328                         image, strerror(errno));
329                 return -EIO;
330         }
331         if (len == 0) {
332                 dev_err(smgr, "Length of file \'%s\' is invalid\n", image);
333                 return -EINVAL;
334         }
335         smgr->rsu_length = len;
336
337         if (smgr->max10_dev->staging_area_size < smgr->rsu_length) {
338                 dev_err(dev, "Size of staging area is small than image length "
339                         "[%u<%u]\n", smgr->max10_dev->staging_area_size,
340                         smgr->rsu_length);
341                 return -EINVAL;
342         }
343
344         printf("Updating from file \'%s\' with size %u\n",
345                 image, smgr->rsu_length);
346
347         sec_mgr = smgr;
348         memset(&sa, 0, sizeof(struct sigaction));
349         sa.sa_flags = SA_SIGINFO | SA_RESETHAND;
350         sa.sa_sigaction = sig_handler;
351         ret = sigaction(SIGINT, &sa, &old_sigint_action);
352         if (ret < 0) {
353                 dev_warn(dev, "Failed to register signal handler"
354                         " [e:%d]\n", ret);
355                 sec_mgr = NULL;
356         }
357
358         start = time(NULL);
359         log_time(time(NULL) - start, "Starting secure flash update");
360         ret = start_flash_update(smgr);
361         if (ret < 0)
362                 goto end;
363
364         set_rsu_status(smgr, IFPGA_RSU_READY, 0);
365         log_time(time(NULL) - start, "Writing to staging area");
366         ret = write_flash_image(smgr, image, 0);
367         if (ret < 0)
368                 goto end;
369
370         set_rsu_status(smgr, IFPGA_RSU_COPYING, 0);
371         log_time(time(NULL) - start, "Applying secure flash update");
372         ret = apply_flash_update(smgr);
373
374 end:
375         if (sec_mgr) {
376                 sec_mgr = NULL;
377                 if (sigaction(SIGINT, &old_sigint_action, NULL) < 0)
378                         dev_err(smgr, "Failed to unregister signal handler\n");
379         }
380
381         secure_update_status(smgr, status);
382         if (ret < 0) {
383                 log_time(time(NULL) - start, "Secure flash update ERROR");
384                 if (ret == -EAGAIN)
385                         secure_update_cancel(smgr);
386         } else {
387                 log_time(time(NULL) - start, "Secure flash update OK");
388         }
389         set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
390
391         return ret;
392 }
393
394 int fpga_stop_flash_update(struct ifpga_fme_hw *fme, int force)
395 {
396         struct ifpga_sec_mgr *smgr = NULL;
397         uint32_t status = 0;
398         int retry = IFPGA_RSU_CANCEL_RETRY;
399         int ret = 0;
400
401         if (!fme) {
402                 dev_err(fme, "Input parameter of %s is invalid\n", __func__);
403                 return -EINVAL;
404         }
405         smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
406
407         get_rsu_status(smgr, &status, NULL);
408         if (status != IFPGA_RSU_IDLE) {
409                 dev_info(smgr, "Cancel secure flash update\n");
410                 set_rsu_control(smgr, IFPGA_RSU_ABORT);
411         }
412
413         if (force) {
414                 sleep(2);
415                 do {
416                         get_rsu_status(smgr, &status, NULL);
417                         if (status == IFPGA_RSU_IDLE)
418                                 break;
419                         if (secure_update_cancel(smgr) == 0)
420                                 set_rsu_status(smgr, IFPGA_RSU_IDLE, 0);
421                         sleep(1);
422                 } while (--retry > 0);
423                 if (retry <= 0) {
424                         dev_err(smgr, "Failed to stop flash update\n");
425                         ret = -EAGAIN;
426                 }
427         }
428
429         return ret;
430 }
431
432 int fpga_reload(struct ifpga_fme_hw *fme, int type, int page)
433 {
434         struct ifpga_sec_mgr *smgr = NULL;
435
436         if (!fme) {
437                 dev_err(fme, "Input parameter of %s is invalid\n", __func__);
438                 return -EINVAL;
439         }
440         smgr = (struct ifpga_sec_mgr *)fme->sec_mgr;
441
442         if (!smgr || !smgr->ops || !smgr->ops->reload)
443                 return -EINVAL;
444
445         return smgr->ops->reload(smgr, type, page);
446 }