• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * drivers/amlogic/media/common/firmware/firmware.c
3  *
4  * Copyright (C) 2016 Amlogic, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14  * more details.
15  *
16  */
17 #include <linux/kernel.h>
18 #include <linux/module.h>
19 #include <linux/types.h>
20 #include <linux/fs.h>
21 #include <linux/init.h>
22 #include <linux/device.h>
23 #include <linux/vmalloc.h>
24 #include <linux/mm.h>
25 #include <linux/slab.h>
26 
27 #include <linux/amlogic/media/utils/vformat.h>
28 #include <linux/amlogic/cpu_version.h>
29 #include "../../stream_input/amports/amports_priv.h"
30 #include "../../frame_provider/decoder/utils/vdec.h"
31 #include "firmware_priv.h"
32 #include "../chips/chips.h"
33 #include <linux/string.h>
34 #include <linux/amlogic/media/utils/log.h>
35 #include <linux/firmware.h>
36 #ifdef CONFIG_AMLOGIC_TEE
37 #include <linux/amlogic/tee.h>
38 #endif
39 #include <linux/amlogic/major.h>
40 #include <linux/cdev.h>
41 #include <linux/crc32.h>
42 #include "../chips/decoder_cpu_ver_info.h"
43 
44 /* major.minor */
45 #define PACK_VERS "v0.2"
46 
47 #define CLASS_NAME	"firmware_codec"
48 #define DEV_NAME	"firmware_vdec"
49 #define DIR		"video"
50 #define FRIMWARE_SIZE	(64 * 1024) /*64k*/
51 #define BUFF_SIZE	(1024 * 1024 * 2)
52 
53 #define FW_LOAD_FORCE	(0x1)
54 #define FW_LOAD_TRY	(0X2)
55 
56 /*the first 256 bytes are signature data*/
57 #define SEC_OFFSET	(256)
58 
59 #define TRY_PARSE_MAX	(256)
60 
61 #define PACK ('P' << 24 | 'A' << 16 | 'C' << 8 | 'K')
62 #define CODE ('C' << 24 | 'O' << 16 | 'D' << 8 | 'E')
63 
64 #ifndef FIRMWARE_MAJOR
65 #define FIRMWARE_MAJOR AMSTREAM_MAJOR
66 #endif
67 
68 static DEFINE_MUTEX(mutex);
69 
70 static  struct ucode_file_info_s ucode_info[] = {
71 #include "firmware_cfg.h"
72 };
73 
74 static const struct file_operations fw_fops = {
75 	.owner = THIS_MODULE
76 };
77 
78 struct fw_mgr_s *g_mgr;
79 struct fw_dev_s *g_dev;
80 
81 static u32 debug;
82 static u32 detail;
83 
84 #ifndef CONFIG_AMLOGIC_TEE
tee_enabled(void)85 static inline bool tee_enabled(void)
86 {
87     return false;
88 }
89 #endif
90 
get_firmware_data(unsigned int format,char * buf)91 int get_firmware_data(unsigned int format, char *buf)
92 {
93 	int data_len, ret = -1;
94 	struct fw_mgr_s *mgr = g_mgr;
95 	struct fw_info_s *info;
96 
97 	pr_info("[%s], the fw (%s) will be loaded.\n",
98 		tee_enabled() ? "TEE" : "LOCAL",
99 		get_fw_format_name(format));
100 
101 	if (tee_enabled())
102 		return 0;
103 
104 	mutex_lock(&mutex);
105 
106 	if (list_empty(&mgr->fw_head)) {
107 		pr_info("the info list is empty.\n");
108 		goto out;
109 	}
110 
111 	list_for_each_entry(info, &mgr->fw_head, node) {
112 		if (format != info->format)
113 			continue;
114 
115 		data_len = info->data->head.data_size;
116 		memcpy(buf, info->data->data, data_len);
117 		ret = data_len;
118 
119 		break;
120 	}
121 out:
122 	mutex_unlock(&mutex);
123 
124 	return ret;
125 }
126 EXPORT_SYMBOL(get_firmware_data);
127 
get_data_from_name(const char * name,char * buf)128 int get_data_from_name(const char *name, char *buf)
129 {
130 	int data_len, ret = -1;
131 	struct fw_mgr_s *mgr = g_mgr;
132 	struct fw_info_s *info;
133 	char *fw_name = __getname();
134 	int len;
135 
136 	if (fw_name == NULL)
137 		return -ENOMEM;
138 
139 	len = snprintf(fw_name, PATH_MAX, "%s.bin", name);
140 	if (len >= PATH_MAX) {
141 		__putname(fw_name);
142 		return -ENAMETOOLONG;
143 	}
144 
145 	mutex_lock(&mutex);
146 
147 	if (list_empty(&mgr->fw_head)) {
148 		pr_info("the info list is empty.\n");
149 		goto out;
150 	}
151 
152 	list_for_each_entry(info, &mgr->fw_head, node) {
153 		if (strcmp(fw_name, info->name))
154 			continue;
155 
156 		data_len = info->data->head.data_size;
157 		memcpy(buf, info->data->data, data_len);
158 		ret = data_len;
159 
160 		break;
161 	}
162 out:
163 	mutex_unlock(&mutex);
164 
165 	__putname(fw_name);
166 
167 	return ret;
168 }
169 EXPORT_SYMBOL(get_data_from_name);
170 
fw_probe(char * buf)171 static int fw_probe(char *buf)
172 {
173 	int magic = 0;
174 
175 	memcpy(&magic, buf, sizeof(int));
176 	return magic;
177 }
178 
request_firmware_from_sys(const char * file_name,char * buf,int size)179 static int request_firmware_from_sys(const char *file_name,
180 		char *buf, int size)
181 {
182 	int ret = -1;
183 	const struct firmware *fw;
184 	int magic, offset = 0;
185 
186 	pr_info("Try to load %s  ...\n", file_name);
187 
188 	ret = request_firmware(&fw, file_name, g_dev->dev);
189 	if (ret < 0) {
190 		pr_info("Error : %d can't load the %s.\n", ret, file_name);
191 		goto err;
192 	}
193 
194 	if (fw->size > size) {
195 		pr_info("Not enough memory size for ucode.\n");
196 		ret = -ENOMEM;
197 		goto release;
198 	}
199 
200 	magic = fw_probe((char *)fw->data);
201 	if (magic != PACK && magic != CODE) {
202 		if (fw->size < SEC_OFFSET) {
203 			pr_info("This is an invalid firmware file.\n");
204 			goto release;
205 		}
206 
207 		magic = fw_probe((char *)fw->data + SEC_OFFSET);
208 		if (magic != PACK) {
209 			pr_info("The firmware file is not packet.\n");
210 			goto release;
211 		}
212 
213 		offset = SEC_OFFSET;
214 	}
215 
216 	memcpy(buf, (char *)fw->data + offset, fw->size - offset);
217 
218 	pr_info("load firmware size : %zd, Name : %s.\n",
219 		fw->size, file_name);
220 	ret = fw->size;
221 release:
222 	release_firmware(fw);
223 err:
224 	return ret;
225 }
226 
request_decoder_firmware_on_sys(enum vformat_e format,const char * file_name,char * buf,int size)227 int request_decoder_firmware_on_sys(enum vformat_e format,
228 	const char *file_name, char *buf, int size)
229 {
230 	int ret;
231 
232 	ret = get_data_from_name(file_name, buf);
233 	if (ret < 0)
234 		pr_info("Get firmware fail.\n");
235 
236 	if (ret > size) {
237 		pr_info("Not enough memory.\n");
238 		return -ENOMEM;
239 	}
240 
241 	return ret;
242 }
get_decoder_firmware_data(enum vformat_e format,const char * file_name,char * buf,int size)243 int get_decoder_firmware_data(enum vformat_e format,
244 	const char *file_name, char *buf, int size)
245 {
246 	int ret;
247 
248 	ret = request_decoder_firmware_on_sys(format, file_name, buf, size);
249 	if (ret < 0)
250 		pr_info("get_decoder_firmware_data %s for format %d failed!\n",
251 				file_name, format);
252 
253 	return ret;
254 }
255 EXPORT_SYMBOL(get_decoder_firmware_data);
256 
fw_mgr_lock(struct fw_mgr_s * mgr)257 static unsigned long fw_mgr_lock(struct fw_mgr_s *mgr)
258 {
259 	unsigned long flags;
260 
261 	spin_lock_irqsave(&mgr->lock, flags);
262 	return flags;
263 }
264 
fw_mgr_unlock(struct fw_mgr_s * mgr,unsigned long flags)265 static void fw_mgr_unlock(struct fw_mgr_s *mgr, unsigned long flags)
266 {
267 	spin_unlock_irqrestore(&mgr->lock, flags);
268 }
269 
fw_add_info(struct fw_info_s * info)270 static void fw_add_info(struct fw_info_s *info)
271 {
272 	unsigned long flags;
273 	struct fw_mgr_s *mgr = g_mgr;
274 
275 	flags = fw_mgr_lock(mgr);
276 	list_add(&info->node, &mgr->fw_head);
277 	fw_mgr_unlock(mgr, flags);
278 }
279 
fw_del_info(struct fw_info_s * info)280 static void fw_del_info(struct fw_info_s *info)
281 {
282 	unsigned long flags;
283 	struct fw_mgr_s *mgr = g_mgr;
284 
285 	flags = fw_mgr_lock(mgr);
286 	list_del(&info->node);
287 	kfree(info);
288 	fw_mgr_unlock(mgr, flags);
289 }
290 
fw_info_walk(void)291 static void fw_info_walk(void)
292 {
293 	struct fw_mgr_s *mgr = g_mgr;
294 	struct fw_info_s *info;
295 
296 	if (list_empty(&mgr->fw_head)) {
297 		pr_info("the info list is empty.\n");
298 		return;
299 	}
300 
301 	list_for_each_entry(info, &mgr->fw_head, node) {
302 		if (IS_ERR_OR_NULL(info->data))
303 			continue;
304 
305 		pr_info("name : %s.\n", info->name);
306 		pr_info("ver  : %s.\n",
307 			info->data->head.version);
308 		pr_info("crc  : 0x%x.\n",
309 			info->data->head.checksum);
310 		pr_info("size : %d.\n",
311 			info->data->head.data_size);
312 		pr_info("maker: %s.\n",
313 			info->data->head.maker);
314 		pr_info("from : %s.\n", info->src_from);
315 		pr_info("date : %s.\n",
316 			info->data->head.date);
317 		if (info->data->head.duplicate)
318 			pr_info("NOTE : Dup from %s.\n",
319 				info->data->head.dup_from);
320 		pr_info("\n");
321 	}
322 }
323 
fw_files_info_walk(void)324 static void fw_files_info_walk(void)
325 {
326 	struct fw_mgr_s *mgr = g_mgr;
327 	struct fw_files_s *files;
328 
329 	if (list_empty(&mgr->files_head)) {
330 		pr_info("the file list is empty.\n");
331 		return;
332 	}
333 
334 	list_for_each_entry(files, &mgr->files_head, node) {
335 		pr_info("type : %s.\n", !files->fw_type ?
336 			"VIDEO_DECODE" : files->fw_type == 1 ?
337 			"VIDEO_ENCODE" : "VIDEO_MISC");
338 		pr_info("from : %s.\n", !files->file_type ?
339 			"VIDEO_PACKAGE" : "VIDEO_FW_FILE");
340 		pr_info("path : %s.\n", files->path);
341 		pr_info("name : %s.\n\n", files->name);
342 	}
343 }
344 
info_show(struct class * class,struct class_attribute * attr,char * buf)345 static ssize_t info_show(struct class *class,
346 			struct class_attribute *attr, char *buf)
347 {
348 	char *pbuf = buf;
349 	struct fw_mgr_s *mgr = g_mgr;
350 	struct fw_info_s *info;
351 	unsigned int secs = 0;
352 	struct tm tm;
353 
354 	mutex_lock(&mutex);
355 
356 	if (list_empty(&mgr->fw_head)) {
357 		pbuf += sprintf(pbuf, "No firmware.\n");
358 		goto out;
359 	}
360 
361 	/* shows version of driver. */
362 	pr_info("The driver version is %s\n", PACK_VERS);
363 
364 	list_for_each_entry(info, &mgr->fw_head, node) {
365 		if (IS_ERR_OR_NULL(info->data))
366 			continue;
367 
368 		if (detail) {
369 			pr_info("%-5s: %s\n", "name", info->name);
370 			pr_info("%-5s: %s\n", "ver",
371 				info->data->head.version);
372 			pr_info("%-5s: 0x%x\n", "sum",
373 				info->data->head.checksum);
374 			pr_info("%-5s: %d\n", "size",
375 				info->data->head.data_size);
376 			pr_info("%-5s: %s\n", "maker",
377 				info->data->head.maker);
378 			pr_info("%-5s: %s\n", "from",
379 				info->src_from);
380 			pr_info("%-5s: %s\n\n", "date",
381 				info->data->head.date);
382 			continue;
383 		}
384 
385 		secs = info->data->head.time
386 			- sys_tz.tz_minuteswest * 60;
387 		time64_to_tm(secs, 0, &tm);
388 
389 		pr_info("%s %-16s, %02d:%02d:%02d %d/%d/%ld, %s %-8s, %s %-8s, %s %s\n",
390 			"fmt:", info->data->head.format,
391 			tm.tm_hour, tm.tm_min, tm.tm_sec,
392 			tm.tm_mon + 1, tm.tm_mday, tm.tm_year + 1900,
393 			"cmtid:", info->data->head.commit,
394 			"chgid:", info->data->head.change_id,
395 			"mk:", info->data->head.maker);
396 	}
397 out:
398 	mutex_unlock(&mutex);
399 
400 	return pbuf - buf;
401 }
402 
info_store(struct class * cls,struct class_attribute * attr,const char * buf,size_t count)403 static ssize_t info_store(struct class *cls,
404 	struct class_attribute *attr, const char *buf, size_t count)
405 {
406 	if (kstrtoint(buf, 0, &detail) < 0)
407 		return -EINVAL;
408 
409 	return count;
410 }
411 
fw_info_fill(void)412 static int fw_info_fill(void)
413 {
414 	int ret = 0, i, len;
415 	struct fw_mgr_s *mgr = g_mgr;
416 	struct fw_files_s *files;
417 	int info_size = ARRAY_SIZE(ucode_info);
418 	char *path = __getname();
419 	const char *name;
420 
421 	if (path == NULL)
422 		return -ENOMEM;
423 
424 	for (i = 0; i < info_size; i++) {
425 		name = ucode_info[i].name;
426 		if (IS_ERR_OR_NULL(name))
427 			break;
428 
429 		len = snprintf(path, PATH_MAX, "%s/%s", DIR,
430 			ucode_info[i].name);
431 		if (len >= PATH_MAX)
432 			continue;
433 
434 		files = kzalloc(sizeof(struct fw_files_s), GFP_KERNEL);
435 		if (files == NULL) {
436 			__putname(path);
437 			return -ENOMEM;
438 		}
439 
440 		files->file_type = ucode_info[i].file_type;
441 		files->fw_type = ucode_info[i].fw_type;
442 		strncpy(files->path, path, sizeof(files->path));
443 		files->path[sizeof(files->path) - 1] = '\0';
444 		strncpy(files->name, name, sizeof(files->name));
445 		files->name[sizeof(files->name) - 1] = '\0';
446 
447 		list_add(&files->node, &mgr->files_head);
448 	}
449 
450 	__putname(path);
451 
452 	if (debug)
453 		fw_files_info_walk();
454 
455 	return ret;
456 }
457 
fw_data_check_sum(struct firmware_s * fw)458 static int fw_data_check_sum(struct firmware_s *fw)
459 {
460 	unsigned int crc;
461 
462 	crc = crc32_le(~0U, fw->data, fw->head.data_size);
463 
464 	/*pr_info("firmware crc result : 0x%x\n", crc ^ ~0U);*/
465 
466 	return fw->head.checksum != (crc ^ ~0U) ? 0 : 1;
467 }
468 
fw_data_filter(struct firmware_s * fw,struct fw_info_s * fw_info)469 static int fw_data_filter(struct firmware_s *fw,
470 	struct fw_info_s *fw_info)
471 {
472 	struct fw_mgr_s *mgr = g_mgr;
473 	struct fw_info_s *info, *tmp;
474 	int cpu = fw_get_cpu(fw->head.cpu);
475 
476 	if (mgr->cur_cpu < cpu) {
477 		kfree(fw_info);
478 		kfree(fw);
479 		return -1;
480 	}
481 
482 	/* the encode fw need to ignoring filtering rules. */
483 	if (fw_info->format == FIRMWARE_MAX)
484 		return 0;
485 
486 	list_for_each_entry_safe(info, tmp, &mgr->fw_head, node) {
487 		if (info->format != fw_info->format)
488 			continue;
489 
490 		if (IS_ERR_OR_NULL(info->data)) {
491 			fw_del_info(info);
492 			return 0;
493 		}
494 
495 		/* high priority of VIDEO_FW_FILE */
496 		if (info->file_type == VIDEO_FW_FILE) {
497 			pr_info("the %s need to priority proc.\n",info->name);
498 			kfree(fw_info);
499 			kfree(fw);
500 			return 1;
501 		}
502 
503 		/* the cpu ver is lower and needs to be filtered */
504 		if (cpu < fw_get_cpu(info->data->head.cpu)) {
505 			if (debug)
506 				pr_info("keep the newer fw (%s) and ignore the older fw (%s).\n",
507 					info->name, fw_info->name);
508 			kfree(fw_info);
509 			kfree(fw);
510 			return 1;
511 		}
512 
513 		/* removes not match fw from info list */
514 		if (debug)
515 			pr_info("drop the old fw (%s) will be load the newer fw (%s).\n",
516 					info->name, fw_info->name);
517 		kfree(info->data);
518 		fw_del_info(info);
519 	}
520 
521 	return 0;
522 }
523 
fw_replace_dup_data(char * buf)524 static int fw_replace_dup_data(char *buf)
525 {
526 	int ret = 0;
527 	struct fw_mgr_s *mgr = g_mgr;
528 	struct package_s *pkg =
529 		(struct package_s *) buf;
530 	struct package_info_s *pinfo =
531 		(struct package_info_s *) pkg->data;
532 	struct fw_info_s *info = NULL;
533 	char *pdata = pkg->data;
534 	int try_cnt = TRY_PARSE_MAX;
535 
536 	do {
537 		if (!pinfo->head.length)
538 			break;
539 		list_for_each_entry(info, &mgr->fw_head, node) {
540 			struct firmware_s *comp = NULL;
541 			struct firmware_s *data = NULL;
542 			int len = 0;
543 
544 			comp = (struct firmware_s *)pinfo->data;
545 			if (comp->head.duplicate)
546 				break;
547 
548 			if (!info->data->head.duplicate ||
549 				comp->head.checksum !=
550 				info->data->head.checksum)
551 				continue;
552 
553 			len = pinfo->head.length;
554 			data = kzalloc(len, GFP_KERNEL);
555 			if (data == NULL) {
556 				ret = -ENOMEM;
557 				goto out;
558 			}
559 
560 			memcpy(data, pinfo->data, len);
561 
562 			/* update header information. */
563 			memcpy(data, info->data, sizeof(*data));
564 
565 			/* if replaced success need to update real size. */
566 			data->head.data_size = comp->head.data_size;
567 
568 			kfree(info->data);
569 			info->data = data;
570 		}
571 		pdata += (pinfo->head.length + sizeof(*pinfo));
572 		pinfo = (struct package_info_s *)pdata;
573 	} while (try_cnt--);
574 out:
575 	return ret;
576 }
577 
fw_check_pack_version(char * buf)578 static int fw_check_pack_version(char *buf)
579 {
580 	struct package_s *pack = NULL;
581 	int major, minor, major_fw, minor_fw;
582 	int ret;
583 
584 	pack = (struct package_s *) buf;
585 	ret = sscanf(PACK_VERS, "v%x.%x", &major, &minor);
586 	if (ret != 2)
587 		return -1;
588 
589 	major_fw = (pack->head.version >> 16) & 0xff;
590 	minor_fw = pack->head.version & 0xff;
591 
592 	if (major < major_fw) {
593 		pr_info("the pack ver v%d.%d too higher to unsupport.\n",
594 			major_fw, minor_fw);
595 		return -1;
596 	}
597 
598 	if (minor < minor_fw) {
599 		pr_info("The fw driver version (v%d.%d) is lower than the pkg version (v%d.%d).\n",
600 			major, minor, major_fw, minor_fw);
601 		pr_info("The driver version is too low that may affect the work please update asap.\n");
602 	}
603 
604 	if (debug) {
605 		pr_info("The package has %d fws totally.\n", pack->head.total);
606 		pr_info("The driver ver is v%d.%d\n", major, minor);
607 		pr_info("The firmware ver is v%d.%d\n", major_fw, minor_fw);
608 	}
609 
610 	return 0;
611 }
612 
fw_package_parse(struct fw_files_s * files,char * buf,int size)613 static int fw_package_parse(struct fw_files_s *files,
614 	char *buf, int size)
615 {
616 	int ret = 0;
617 	struct package_info_s *pack_info;
618 	struct fw_info_s *info;
619 	struct firmware_s *data;
620 	char *pack_data;
621 	int info_len, len;
622 	int try_cnt = TRY_PARSE_MAX;
623 	char *path = __getname();
624 
625 	if (path == NULL)
626 		return -ENOMEM;
627 
628 	pack_data = ((struct package_s *)buf)->data;
629 	pack_info = (struct package_info_s *)pack_data;
630 	info_len = sizeof(struct package_info_s);
631 
632 	do {
633 		if (!pack_info->head.length)
634 			break;
635 
636 		len = snprintf(path, PATH_MAX, "%s/%s", DIR,
637 			pack_info->head.name);
638 		if (len >= PATH_MAX)
639 			continue;
640 
641 		info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL);
642 		if (info == NULL) {
643 			ret = -ENOMEM;
644 			goto out;
645 		}
646 
647 		data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL);
648 		if (data == NULL) {
649 			kfree(info);
650 			ret = -ENOMEM;
651 			goto out;
652 		}
653 
654 		info->file_type = files->file_type;
655 		strncpy(info->src_from, files->name,
656 			sizeof(info->src_from));
657 		info->src_from[sizeof(info->src_from) - 1] = '\0';
658 		strncpy(info->name, pack_info->head.name,
659 			sizeof(info->name));
660 		info->name[sizeof(info->name) - 1] = '\0';
661 		info->format = get_fw_format(pack_info->head.format);
662 
663 		len = pack_info->head.length;
664 		memcpy(data, pack_info->data, len);
665 
666 		pack_data += (pack_info->head.length + info_len);
667 		pack_info = (struct package_info_s *)pack_data;
668 
669 		if (!data->head.duplicate &&
670 			!fw_data_check_sum(data)) {
671 			pr_info("check sum fail !\n");
672 			kfree(data);
673 			kfree(info);
674 			goto out;
675 		}
676 
677 		if (fw_data_filter(data, info))
678 			continue;
679 
680 		if (debug)
681 			pr_info("adds %s to the fw list.\n", info->name);
682 
683 		info->data = data;
684 		fw_add_info(info);
685 	} while (try_cnt--);
686 
687 	/* process the fw of dup attribute. */
688 	ret = fw_replace_dup_data(buf);
689 	if (ret)
690 		pr_err("replace dup fw failed.\n");
691 out:
692 	__putname(path);
693 
694 	return ret;
695 }
696 
fw_code_parse(struct fw_files_s * files,char * buf,int size)697 static int fw_code_parse(struct fw_files_s *files,
698 	char *buf, int size)
699 {
700 	struct fw_info_s *info;
701 
702 	info = kzalloc(sizeof(struct fw_info_s), GFP_KERNEL);
703 	if (info == NULL)
704 		return -ENOMEM;
705 
706 	info->data = kzalloc(FRIMWARE_SIZE, GFP_KERNEL);
707 	if (info->data == NULL) {
708 		kfree(info);
709 		return -ENOMEM;
710 	}
711 
712 	info->file_type = files->file_type;
713 	strncpy(info->src_from, files->name,
714 		sizeof(info->src_from));
715 	info->src_from[sizeof(info->src_from) - 1] = '\0';
716 	memcpy(info->data, buf, size);
717 
718 	if (!fw_data_check_sum(info->data)) {
719 		pr_info("check sum fail !\n");
720 		kfree(info->data);
721 		kfree(info);
722 		return -1;
723 	}
724 
725 	if (debug)
726 		pr_info("adds %s to the fw list.\n", info->name);
727 
728 	fw_add_info(info);
729 
730 	return 0;
731 }
732 
get_firmware_from_sys(const char * path,char * buf,int size)733 static int get_firmware_from_sys(const char *path,
734 	char *buf, int size)
735 {
736 	int len = 0;
737 
738 	len = request_firmware_from_sys(path, buf, size);
739 	if (len < 0)
740 		pr_info("get data from fsys fail.\n");
741 
742 	return len;
743 }
744 
fw_data_binding(void)745 static int fw_data_binding(void)
746 {
747 	int ret = 0, magic = 0;
748 	struct fw_mgr_s *mgr = g_mgr;
749 	struct fw_files_s *files, *tmp;
750 	char *buf = NULL;
751 	int size;
752 
753 	if (list_empty(&mgr->files_head)) {
754 		pr_info("the file list is empty.\n");
755 		return 0;
756 	}
757 
758 	buf = vmalloc(BUFF_SIZE);
759 	if (IS_ERR_OR_NULL(buf))
760 		return -ENOMEM;
761 
762 	memset(buf, 0, BUFF_SIZE);
763 
764 	list_for_each_entry_safe(files, tmp, &mgr->files_head, node) {
765 		size = get_firmware_from_sys(files->path, buf, BUFF_SIZE);
766 		magic = fw_probe(buf);
767 
768 		if (files->file_type == VIDEO_PACKAGE && magic == PACK) {
769 			if (!fw_check_pack_version(buf))
770 				ret = fw_package_parse(files, buf, size);
771 		} else if (files->file_type == VIDEO_FW_FILE && magic == CODE) {
772 			ret = fw_code_parse(files, buf, size);
773 		} else {
774 			list_del(&files->node);
775 			kfree(files);
776 			pr_info("invaild file type.\n");
777 		}
778 
779 		memset(buf, 0, BUFF_SIZE);
780 	}
781 
782 	if (debug)
783 		fw_info_walk();
784 
785 	vfree(buf);
786 
787 	return ret;
788 }
789 
fw_pre_load(void)790 static int fw_pre_load(void)
791 {
792 	if (fw_info_fill() < 0) {
793 		pr_info("Get path fail.\n");
794 		return -1;
795 	}
796 
797 	if (fw_data_binding() < 0) {
798 		pr_info("Set data fail.\n");
799 		return -1;
800 	}
801 
802 	return 0;
803 }
804 
fw_mgr_init(void)805 static int fw_mgr_init(void)
806 {
807 	g_mgr = kzalloc(sizeof(struct fw_mgr_s), GFP_KERNEL);
808 	if (IS_ERR_OR_NULL(g_mgr))
809 		return -ENOMEM;
810 
811 	g_mgr->cur_cpu = get_cpu_major_id();
812 	INIT_LIST_HEAD(&g_mgr->files_head);
813 	INIT_LIST_HEAD(&g_mgr->fw_head);
814 	spin_lock_init(&g_mgr->lock);
815 
816 	return 0;
817 }
818 
fw_ctx_clean(void)819 static void fw_ctx_clean(void)
820 {
821 	struct fw_mgr_s *mgr = g_mgr;
822 	struct fw_files_s *files;
823 	struct fw_info_s *info;
824 	unsigned long flags;
825 
826 	flags = fw_mgr_lock(mgr);
827 	while (!list_empty(&mgr->files_head)) {
828 		files = list_entry(mgr->files_head.next,
829 			struct fw_files_s, node);
830 		list_del(&files->node);
831 		kfree(files);
832 	}
833 
834 	while (!list_empty(&mgr->fw_head)) {
835 		info = list_entry(mgr->fw_head.next,
836 			struct fw_info_s, node);
837 		list_del(&info->node);
838 		kfree(info->data);
839 		kfree(info);
840 	}
841 	fw_mgr_unlock(mgr, flags);
842 }
843 
video_fw_reload(int mode)844 int video_fw_reload(int mode)
845 {
846 	int ret = 0;
847 	struct fw_mgr_s *mgr = g_mgr;
848 
849 	if (tee_enabled())
850 		return 0;
851 
852 	mutex_lock(&mutex);
853 
854 	if (mode & FW_LOAD_FORCE) {
855 		fw_ctx_clean();
856 
857 		ret = fw_pre_load();
858 		if (ret < 0)
859 			pr_err("The fw reload fail.\n");
860 	} else if (mode & FW_LOAD_TRY) {
861 		if (!list_empty(&mgr->fw_head)) {
862 			pr_info("The fw has been loaded.\n");
863 			goto out;
864 		}
865 
866 		ret = fw_pre_load();
867 		if (ret < 0)
868 			pr_err("The fw try to reload fail.\n");
869 	}
870 out:
871 	mutex_unlock(&mutex);
872 
873 	return ret;
874 }
875 EXPORT_SYMBOL(video_fw_reload);
876 
reload_show(struct class * class,struct class_attribute * attr,char * buf)877 static ssize_t reload_show(struct class *class,
878 			struct class_attribute *attr, char *buf)
879 {
880 	char *pbuf = buf;
881 
882 	pbuf += sprintf(pbuf, "The fw reload usage.\n");
883 	pbuf += sprintf(pbuf, "> set 1 means that the fw is forced to update\n");
884 	pbuf += sprintf(pbuf, "> set 2 means that the fw is try to reload\n");
885 
886 	return pbuf - buf;
887 }
888 
reload_store(struct class * class,struct class_attribute * attr,const char * buf,size_t size)889 static ssize_t reload_store(struct class *class,
890 		struct class_attribute *attr,
891 		const char *buf, size_t size)
892 {
893 	int ret = -1;
894 	unsigned int val;
895 
896 	ret = kstrtoint(buf, 0, &val);
897 	if (ret != 0)
898 		return -EINVAL;
899 
900 	ret = video_fw_reload(val);
901 	if (ret < 0)
902 		pr_err("fw reload fail.\n");
903 
904 	return size;
905 }
906 
debug_show(struct class * cls,struct class_attribute * attr,char * buf)907 static ssize_t debug_show(struct class *cls,
908 	struct class_attribute *attr, char *buf)
909 {
910 	return sprintf(buf, "%x\n", debug);
911 }
912 
debug_store(struct class * cls,struct class_attribute * attr,const char * buf,size_t count)913 static ssize_t debug_store(struct class *cls,
914 	struct class_attribute *attr, const char *buf, size_t count)
915 {
916 	if (kstrtoint(buf, 0, &debug) < 0)
917 		return -EINVAL;
918 
919 	return count;
920 }
921 
922 static CLASS_ATTR_RW(info);
923 static CLASS_ATTR_RW(reload);
924 static CLASS_ATTR_RW(debug);
925 
926 static struct attribute *fw_class_attrs[] = {
927 	&class_attr_info.attr,
928 	&class_attr_reload.attr,
929 	&class_attr_debug.attr,
930 	NULL
931 };
932 
933 ATTRIBUTE_GROUPS(fw_class);
934 
935 static struct class fw_class = {
936 	.name = CLASS_NAME,
937 	.class_groups = fw_class_groups,
938 };
939 
fw_driver_init(void)940 static int fw_driver_init(void)
941 {
942 	int ret = -1;
943 
944 	g_dev = kzalloc(sizeof(struct fw_dev_s), GFP_KERNEL);
945 	if (IS_ERR_OR_NULL(g_dev))
946 		return -ENOMEM;
947 
948 	g_dev->dev_no = MKDEV(FIRMWARE_MAJOR, 100);
949 
950 	ret = register_chrdev_region(g_dev->dev_no, 1, DEV_NAME);
951 	if (ret < 0) {
952 		pr_info("Can't get major number %d.\n", FIRMWARE_MAJOR);
953 		goto err;
954 	}
955 
956 	cdev_init(&g_dev->cdev, &fw_fops);
957 	g_dev->cdev.owner = THIS_MODULE;
958 
959 	ret = cdev_add(&g_dev->cdev, g_dev->dev_no, 1);
960 	if (ret) {
961 		pr_info("Error %d adding cdev fail.\n", ret);
962 		goto err;
963 	}
964 
965 	ret = class_register(&fw_class);
966 	if (ret < 0) {
967 		pr_info("Failed in creating class.\n");
968 		goto err;
969 	}
970 
971 	g_dev->dev = device_create(&fw_class, NULL,
972 		g_dev->dev_no, NULL, DEV_NAME);
973 	if (IS_ERR_OR_NULL(g_dev->dev)) {
974 		pr_info("Create device failed.\n");
975 		ret = -ENODEV;
976 		goto err;
977 	}
978 
979 	pr_info("Registered firmware driver success.\n");
980 err:
981 	return ret;
982 }
983 
fw_driver_exit(void)984 static void fw_driver_exit(void)
985 {
986 	cdev_del(&g_dev->cdev);
987 	device_destroy(&fw_class, g_dev->dev_no);
988 	class_unregister(&fw_class);
989 	unregister_chrdev_region(g_dev->dev_no, 1);
990 	kfree(g_dev);
991 	kfree(g_mgr);
992 }
993 
fw_module_init(void)994 static int __init fw_module_init(void)
995 {
996 	int ret = -1;
997 
998 	ret = fw_driver_init();
999 	if (ret) {
1000 		pr_info("Error %d firmware driver init fail.\n", ret);
1001 		goto err;
1002 	}
1003 
1004 	ret = fw_mgr_init();
1005 	if (ret) {
1006 		pr_info("Error %d firmware mgr init fail.\n", ret);
1007 		goto err;
1008 	}
1009 
1010 	ret = fw_pre_load();
1011 	if (ret) {
1012 		pr_info("Error %d firmware pre load fail.\n", ret);
1013 		goto err;
1014 	}
1015 err:
1016 	return ret;
1017 }
1018 
fw_module_exit(void)1019 static void __exit fw_module_exit(void)
1020 {
1021 	fw_ctx_clean();
1022 	fw_driver_exit();
1023 	pr_info("Firmware driver cleaned up.\n");
1024 }
1025 
1026 module_init(fw_module_init);
1027 module_exit(fw_module_exit);
1028 
1029 MODULE_LICENSE("GPL");
1030 MODULE_AUTHOR("Nanxin Qin <nanxin.qin@amlogic.com>");
1031