1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2015
4  * Lukasz Majewski <l.majewski@majess.pl>
5  */
6 
7 #include <common.h>
8 #include <log.h>
9 #include <malloc.h>
10 #include <errno.h>
11 #include <dfu.h>
12 
13 /**
14  * dfu_write_by_name() - write data to DFU medium
15  * @dfu_entity_name:    Name of DFU entity to write
16  * @addr:               Address of data buffer to write
17  * @len:                Number of bytes
18  * @interface:          Destination DFU medium (e.g. "mmc")
19  * @devstring:          Instance number of destination DFU medium (e.g. "1")
20  *
21  * This function is storing data received on DFU supported medium which
22  * is specified by @dfu_entity_name.
23  *
24  * Return:              0 - on success, error code - otherwise
25  */
dfu_write_by_name(char * dfu_entity_name,void * addr,unsigned int len,char * interface,char * devstring)26 int dfu_write_by_name(char *dfu_entity_name, void *addr,
27 		      unsigned int len, char *interface, char *devstring)
28 {
29 	char *s, *sb;
30 	int alt_setting_num, ret;
31 	struct dfu_entity *dfu;
32 
33 	debug("%s: name: %s addr: 0x%p len: %d device: %s:%s\n", __func__,
34 	      dfu_entity_name, addr, len, interface, devstring);
35 
36 	ret = dfu_init_env_entities(interface, devstring);
37 	if (ret)
38 		goto done;
39 
40 	/*
41 	 * We need to copy name pointed by *dfu_entity_name since this text
42 	 * is the integral part of the FDT image.
43 	 * Any implicit modification (i.e. done by strsep()) will corrupt
44 	 * the FDT image and prevent other images to be stored.
45 	 */
46 	s = strdup(dfu_entity_name);
47 	sb = s;
48 	if (!s) {
49 		ret = -ENOMEM;
50 		goto done;
51 	}
52 
53 	strsep(&s, "@");
54 	debug("%s: image name: %s strlen: %zd\n", __func__, sb, strlen(sb));
55 
56 	alt_setting_num = dfu_get_alt(sb);
57 	free(sb);
58 	if (alt_setting_num < 0) {
59 		pr_err("Alt setting [%d] to write not found!",
60 		       alt_setting_num);
61 		ret = -ENODEV;
62 		goto done;
63 	}
64 
65 	dfu = dfu_get_entity(alt_setting_num);
66 	if (!dfu) {
67 		pr_err("DFU entity for alt: %d not found!", alt_setting_num);
68 		ret = -ENODEV;
69 		goto done;
70 	}
71 
72 	ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
73 
74 done:
75 	dfu_free_entities();
76 
77 	return ret;
78 }
79 
80 /**
81  * dfu_write_by_alt() - write data to DFU medium
82  * @dfu_alt_num:        DFU alt setting number
83  * @addr:               Address of data buffer to write
84  * @len:                Number of bytes
85  * @interface:          Destination DFU medium (e.g. "mmc")
86  * @devstring:          Instance number of destination DFU medium (e.g. "1")
87  *
88  * This function is storing data received on DFU supported medium which
89  * is specified by @dfu_alt_name.
90  *
91  * Return:              0 - on success, error code - otherwise
92  */
dfu_write_by_alt(int dfu_alt_num,void * addr,unsigned int len,char * interface,char * devstring)93 int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
94 		     char *interface, char *devstring)
95 {
96 	struct dfu_entity *dfu;
97 	int ret;
98 
99 	debug("%s: alt: %d addr: 0x%p len: %d device: %s:%s\n", __func__,
100 	      dfu_alt_num, addr, len, interface, devstring);
101 
102 	ret = dfu_init_env_entities(interface, devstring);
103 	if (ret)
104 		goto done;
105 
106 	if (dfu_alt_num < 0) {
107 		pr_err("Invalid alt number: %d", dfu_alt_num);
108 		ret = -ENODEV;
109 		goto done;
110 	}
111 
112 	dfu = dfu_get_entity(dfu_alt_num);
113 	if (!dfu) {
114 		pr_err("DFU entity for alt: %d not found!", dfu_alt_num);
115 		ret = -ENODEV;
116 		goto done;
117 	}
118 
119 	ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
120 
121 done:
122 	dfu_free_entities();
123 
124 	return ret;
125 }
126