xref: /dpdk/drivers/raw/ifpga/base/ifpga_fme_rsu.c (revision bf95921a01acc341442cb42c4764c05334e4412b)
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 
set_rsu_control(struct ifpga_sec_mgr * smgr,uint32_t ctrl)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 
get_rsu_control(struct ifpga_sec_mgr * smgr)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 
set_rsu_status(struct ifpga_sec_mgr * smgr,uint32_t status,uint32_t progress)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 
get_rsu_status(struct ifpga_sec_mgr * smgr,uint32_t * status,uint32_t * progress)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 
sig_handler(int sig,siginfo_t * info,void * data)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 
log_time(time_t t,const char * msg)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 
start_flash_update(struct ifpga_sec_mgr * smgr)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 
write_flash_image(struct ifpga_sec_mgr * smgr,const char * image,uint32_t offset)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 
apply_flash_update(struct ifpga_sec_mgr * smgr)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 
secure_update_cancel(struct ifpga_sec_mgr * smgr)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 
secure_update_status(struct ifpga_sec_mgr * smgr,uint64_t * status)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 
fpga_update_flash(struct ifpga_fme_hw * fme,const char * image,uint64_t * status)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 
fpga_stop_flash_update(struct ifpga_fme_hw * fme,int force)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 
fpga_reload(struct ifpga_fme_hw * fme,int type,int page)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 }
447