1
2
3
4
5#include <fcntl.h>
6#include <signal.h>
7#include <unistd.h>
8#include "ifpga_sec_mgr.h"
9
10static struct ifpga_sec_mgr *sec_mgr;
11
12static 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
18static 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
25static 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
32static 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
43static 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
61static 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
80static 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
91static 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
184end:
185 free(buf);
186 close(fd);
187 return ret;
188}
189
190static 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)
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)
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
246static 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
257static 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
271int 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
374end:
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
394int 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
432int 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}
447