xref: /rk3399_rockchip-uboot/drivers/dfu/dfu.c (revision ea2453d56b8860dbd18a3c517531ffc8dcb5c839)
1f22b11c1SLukasz Majewski /*
2f22b11c1SLukasz Majewski  * dfu.c -- DFU back-end routines
3f22b11c1SLukasz Majewski  *
4f22b11c1SLukasz Majewski  * Copyright (C) 2012 Samsung Electronics
5f22b11c1SLukasz Majewski  * author: Lukasz Majewski <l.majewski@samsung.com>
6f22b11c1SLukasz Majewski  *
7f22b11c1SLukasz Majewski  * This program is free software; you can redistribute it and/or modify
8f22b11c1SLukasz Majewski  * it under the terms of the GNU General Public License as published by
9f22b11c1SLukasz Majewski  * the Free Software Foundation; either version 2 of the License, or
10f22b11c1SLukasz Majewski  * (at your option) any later version.
11f22b11c1SLukasz Majewski  *
12f22b11c1SLukasz Majewski  * This program is distributed in the hope that it will be useful,
13f22b11c1SLukasz Majewski  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14f22b11c1SLukasz Majewski  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15f22b11c1SLukasz Majewski  * GNU General Public License for more details.
16f22b11c1SLukasz Majewski  *
17f22b11c1SLukasz Majewski  * You should have received a copy of the GNU General Public License
18f22b11c1SLukasz Majewski  * along with this program; if not, write to the Free Software
19f22b11c1SLukasz Majewski  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20f22b11c1SLukasz Majewski  */
21f22b11c1SLukasz Majewski 
22f22b11c1SLukasz Majewski #include <common.h>
23f22b11c1SLukasz Majewski #include <malloc.h>
24f22b11c1SLukasz Majewski #include <mmc.h>
25f22b11c1SLukasz Majewski #include <fat.h>
26f22b11c1SLukasz Majewski #include <dfu.h>
27f22b11c1SLukasz Majewski #include <linux/list.h>
28f22b11c1SLukasz Majewski #include <linux/compiler.h>
29f22b11c1SLukasz Majewski 
30f22b11c1SLukasz Majewski static LIST_HEAD(dfu_list);
31f22b11c1SLukasz Majewski static int dfu_alt_num;
32f22b11c1SLukasz Majewski 
33f22b11c1SLukasz Majewski static int dfu_find_alt_num(const char *s)
34f22b11c1SLukasz Majewski {
35f22b11c1SLukasz Majewski 	int i = 0;
36f22b11c1SLukasz Majewski 
37f22b11c1SLukasz Majewski 	for (; *s; s++)
38f22b11c1SLukasz Majewski 		if (*s == ';')
39f22b11c1SLukasz Majewski 			i++;
40f22b11c1SLukasz Majewski 
41f22b11c1SLukasz Majewski 	return ++i;
42f22b11c1SLukasz Majewski }
43f22b11c1SLukasz Majewski 
44f22b11c1SLukasz Majewski static unsigned char __aligned(CONFIG_SYS_CACHELINE_SIZE)
45f22b11c1SLukasz Majewski 				     dfu_buf[DFU_DATA_BUF_SIZE];
46f22b11c1SLukasz Majewski 
47*ea2453d5SPantelis Antoniou static int dfu_write_buffer_drain(struct dfu_entity *dfu)
48f22b11c1SLukasz Majewski {
49*ea2453d5SPantelis Antoniou 	long w_size;
50*ea2453d5SPantelis Antoniou 	int ret;
51f22b11c1SLukasz Majewski 
52*ea2453d5SPantelis Antoniou 	/* flush size? */
53*ea2453d5SPantelis Antoniou 	w_size = dfu->i_buf - dfu->i_buf_start;
54*ea2453d5SPantelis Antoniou 	if (w_size == 0)
55*ea2453d5SPantelis Antoniou 		return 0;
56f22b11c1SLukasz Majewski 
57*ea2453d5SPantelis Antoniou 	/* update CRC32 */
58*ea2453d5SPantelis Antoniou 	dfu->crc = crc32(dfu->crc, dfu->i_buf_start, w_size);
59f22b11c1SLukasz Majewski 
60*ea2453d5SPantelis Antoniou 	ret = dfu->write_medium(dfu, dfu->offset, dfu->i_buf_start, &w_size);
61f22b11c1SLukasz Majewski 	if (ret)
62f22b11c1SLukasz Majewski 		debug("%s: Write error!\n", __func__);
63f22b11c1SLukasz Majewski 
64*ea2453d5SPantelis Antoniou 	/* point back */
65*ea2453d5SPantelis Antoniou 	dfu->i_buf = dfu->i_buf_start;
66*ea2453d5SPantelis Antoniou 
67*ea2453d5SPantelis Antoniou 	/* update offset */
68*ea2453d5SPantelis Antoniou 	dfu->offset += w_size;
69*ea2453d5SPantelis Antoniou 
70*ea2453d5SPantelis Antoniou 	puts("#");
71*ea2453d5SPantelis Antoniou 
72f22b11c1SLukasz Majewski 	return ret;
73f22b11c1SLukasz Majewski }
74f22b11c1SLukasz Majewski 
75*ea2453d5SPantelis Antoniou int dfu_write(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
76*ea2453d5SPantelis Antoniou {
77*ea2453d5SPantelis Antoniou 	int ret = 0;
78*ea2453d5SPantelis Antoniou 	int tret;
79*ea2453d5SPantelis Antoniou 
80*ea2453d5SPantelis Antoniou 	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x offset: 0x%llx bufoffset: 0x%x\n",
81*ea2453d5SPantelis Antoniou 	      __func__, dfu->name, buf, size, blk_seq_num, dfu->offset,
82*ea2453d5SPantelis Antoniou 	      dfu->i_buf - dfu->i_buf_start);
83*ea2453d5SPantelis Antoniou 
84*ea2453d5SPantelis Antoniou 	if (!dfu->inited) {
85*ea2453d5SPantelis Antoniou 		/* initial state */
86*ea2453d5SPantelis Antoniou 		dfu->crc = 0;
87*ea2453d5SPantelis Antoniou 		dfu->offset = 0;
88*ea2453d5SPantelis Antoniou 		dfu->i_blk_seq_num = 0;
89*ea2453d5SPantelis Antoniou 		dfu->i_buf_start = dfu_buf;
90*ea2453d5SPantelis Antoniou 		dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
91*ea2453d5SPantelis Antoniou 		dfu->i_buf = dfu->i_buf_start;
92*ea2453d5SPantelis Antoniou 
93*ea2453d5SPantelis Antoniou 		dfu->inited = 1;
94*ea2453d5SPantelis Antoniou 	}
95*ea2453d5SPantelis Antoniou 
96*ea2453d5SPantelis Antoniou 	if (dfu->i_blk_seq_num != blk_seq_num) {
97*ea2453d5SPantelis Antoniou 		printf("%s: Wrong sequence number! [%d] [%d]\n",
98*ea2453d5SPantelis Antoniou 		       __func__, dfu->i_blk_seq_num, blk_seq_num);
99*ea2453d5SPantelis Antoniou 		return -1;
100*ea2453d5SPantelis Antoniou 	}
101*ea2453d5SPantelis Antoniou 
102*ea2453d5SPantelis Antoniou 	/* DFU 1.1 standard says:
103*ea2453d5SPantelis Antoniou 	 * The wBlockNum field is a block sequence number. It increments each
104*ea2453d5SPantelis Antoniou 	 * time a block is transferred, wrapping to zero from 65,535. It is used
105*ea2453d5SPantelis Antoniou 	 * to provide useful context to the DFU loader in the device."
106*ea2453d5SPantelis Antoniou 	 *
107*ea2453d5SPantelis Antoniou 	 * This means that it's a 16 bit counter that roll-overs at
108*ea2453d5SPantelis Antoniou 	 * 0xffff -> 0x0000. By having a typical 4K transfer block
109*ea2453d5SPantelis Antoniou 	 * we roll-over at exactly 256MB. Not very fun to debug.
110*ea2453d5SPantelis Antoniou 	 *
111*ea2453d5SPantelis Antoniou 	 * Handling rollover, and having an inited variable,
112*ea2453d5SPantelis Antoniou 	 * makes things work.
113*ea2453d5SPantelis Antoniou 	 */
114*ea2453d5SPantelis Antoniou 
115*ea2453d5SPantelis Antoniou 	/* handle rollover */
116*ea2453d5SPantelis Antoniou 	dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
117*ea2453d5SPantelis Antoniou 
118*ea2453d5SPantelis Antoniou 	/* flush buffer if overflow */
119*ea2453d5SPantelis Antoniou 	if ((dfu->i_buf + size) > dfu->i_buf_end) {
120*ea2453d5SPantelis Antoniou 		tret = dfu_write_buffer_drain(dfu);
121*ea2453d5SPantelis Antoniou 		if (ret == 0)
122*ea2453d5SPantelis Antoniou 			ret = tret;
123*ea2453d5SPantelis Antoniou 	}
124*ea2453d5SPantelis Antoniou 
125*ea2453d5SPantelis Antoniou 	/* we should be in buffer now (if not then size too large) */
126*ea2453d5SPantelis Antoniou 	if ((dfu->i_buf + size) > dfu->i_buf_end) {
127*ea2453d5SPantelis Antoniou 		printf("%s: Wrong size! [%d] [%d] - %d\n",
128*ea2453d5SPantelis Antoniou 		       __func__, dfu->i_blk_seq_num, blk_seq_num, size);
129*ea2453d5SPantelis Antoniou 		return -1;
130*ea2453d5SPantelis Antoniou 	}
131*ea2453d5SPantelis Antoniou 
132*ea2453d5SPantelis Antoniou 	memcpy(dfu->i_buf, buf, size);
133*ea2453d5SPantelis Antoniou 	dfu->i_buf += size;
134*ea2453d5SPantelis Antoniou 
135*ea2453d5SPantelis Antoniou 	/* if end or if buffer full flush */
136*ea2453d5SPantelis Antoniou 	if (size == 0 || (dfu->i_buf + size) > dfu->i_buf_end) {
137*ea2453d5SPantelis Antoniou 		tret = dfu_write_buffer_drain(dfu);
138*ea2453d5SPantelis Antoniou 		if (ret == 0)
139*ea2453d5SPantelis Antoniou 			ret = tret;
140*ea2453d5SPantelis Antoniou 	}
141*ea2453d5SPantelis Antoniou 
142*ea2453d5SPantelis Antoniou 	/* end? */
143*ea2453d5SPantelis Antoniou 	if (size == 0) {
144*ea2453d5SPantelis Antoniou 		/* Now try and flush to the medium if needed. */
145*ea2453d5SPantelis Antoniou 		if (dfu->flush_medium)
146*ea2453d5SPantelis Antoniou 			ret = dfu->flush_medium(dfu);
147*ea2453d5SPantelis Antoniou 		printf("\nDFU complete CRC32: 0x%08x\n", dfu->crc);
148*ea2453d5SPantelis Antoniou 
149*ea2453d5SPantelis Antoniou 		/* clear everything */
150*ea2453d5SPantelis Antoniou 		dfu->crc = 0;
151*ea2453d5SPantelis Antoniou 		dfu->offset = 0;
152*ea2453d5SPantelis Antoniou 		dfu->i_blk_seq_num = 0;
153*ea2453d5SPantelis Antoniou 		dfu->i_buf_start = dfu_buf;
154*ea2453d5SPantelis Antoniou 		dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
155*ea2453d5SPantelis Antoniou 		dfu->i_buf = dfu->i_buf_start;
156*ea2453d5SPantelis Antoniou 
157*ea2453d5SPantelis Antoniou 		dfu->inited = 0;
158*ea2453d5SPantelis Antoniou 
159*ea2453d5SPantelis Antoniou 	}
160*ea2453d5SPantelis Antoniou 
161*ea2453d5SPantelis Antoniou 	return ret = 0 ? size : ret;
162*ea2453d5SPantelis Antoniou }
163*ea2453d5SPantelis Antoniou 
164*ea2453d5SPantelis Antoniou static int dfu_read_buffer_fill(struct dfu_entity *dfu, void *buf, int size)
165*ea2453d5SPantelis Antoniou {
166*ea2453d5SPantelis Antoniou 	long chunk;
167*ea2453d5SPantelis Antoniou 	int ret, readn;
168*ea2453d5SPantelis Antoniou 
169*ea2453d5SPantelis Antoniou 	readn = 0;
170*ea2453d5SPantelis Antoniou 	while (size > 0) {
171*ea2453d5SPantelis Antoniou 		/* get chunk that can be read */
172*ea2453d5SPantelis Antoniou 		chunk = min(size, dfu->b_left);
173*ea2453d5SPantelis Antoniou 		/* consume */
174*ea2453d5SPantelis Antoniou 		if (chunk > 0) {
175*ea2453d5SPantelis Antoniou 			memcpy(buf, dfu->i_buf, chunk);
176*ea2453d5SPantelis Antoniou 			dfu->crc = crc32(dfu->crc, buf, chunk);
177*ea2453d5SPantelis Antoniou 			dfu->i_buf += chunk;
178*ea2453d5SPantelis Antoniou 			dfu->b_left -= chunk;
179*ea2453d5SPantelis Antoniou 			size -= chunk;
180*ea2453d5SPantelis Antoniou 			buf += chunk;
181*ea2453d5SPantelis Antoniou 			readn += chunk;
182*ea2453d5SPantelis Antoniou 		}
183*ea2453d5SPantelis Antoniou 
184*ea2453d5SPantelis Antoniou 		/* all done */
185*ea2453d5SPantelis Antoniou 		if (size > 0) {
186*ea2453d5SPantelis Antoniou 			/* no more to read */
187*ea2453d5SPantelis Antoniou 			if (dfu->r_left == 0)
188*ea2453d5SPantelis Antoniou 				break;
189*ea2453d5SPantelis Antoniou 
190*ea2453d5SPantelis Antoniou 			dfu->i_buf = dfu->i_buf_start;
191*ea2453d5SPantelis Antoniou 			dfu->b_left = dfu->i_buf_end - dfu->i_buf_start;
192*ea2453d5SPantelis Antoniou 
193*ea2453d5SPantelis Antoniou 			/* got to read, but buffer is empty */
194*ea2453d5SPantelis Antoniou 			if (dfu->b_left > dfu->r_left)
195*ea2453d5SPantelis Antoniou 				dfu->b_left = dfu->r_left;
196*ea2453d5SPantelis Antoniou 			ret = dfu->read_medium(dfu, dfu->offset, dfu->i_buf,
197*ea2453d5SPantelis Antoniou 					&dfu->b_left);
198*ea2453d5SPantelis Antoniou 			if (ret != 0) {
199*ea2453d5SPantelis Antoniou 				debug("%s: Read error!\n", __func__);
200f22b11c1SLukasz Majewski 				return ret;
201f22b11c1SLukasz Majewski 			}
202*ea2453d5SPantelis Antoniou 			dfu->offset += dfu->b_left;
203*ea2453d5SPantelis Antoniou 			dfu->r_left -= dfu->b_left;
204*ea2453d5SPantelis Antoniou 
205*ea2453d5SPantelis Antoniou 			puts("#");
206*ea2453d5SPantelis Antoniou 		}
207*ea2453d5SPantelis Antoniou 	}
208*ea2453d5SPantelis Antoniou 
209*ea2453d5SPantelis Antoniou 	return readn;
210*ea2453d5SPantelis Antoniou }
211f22b11c1SLukasz Majewski 
212f22b11c1SLukasz Majewski int dfu_read(struct dfu_entity *dfu, void *buf, int size, int blk_seq_num)
213f22b11c1SLukasz Majewski {
214f22b11c1SLukasz Majewski 	int ret = 0;
215f22b11c1SLukasz Majewski 
216f22b11c1SLukasz Majewski 	debug("%s: name: %s buf: 0x%p size: 0x%x p_num: 0x%x i_buf: 0x%p\n",
217*ea2453d5SPantelis Antoniou 	       __func__, dfu->name, buf, size, blk_seq_num, dfu->i_buf);
218f22b11c1SLukasz Majewski 
219*ea2453d5SPantelis Antoniou 	if (!dfu->inited) {
220*ea2453d5SPantelis Antoniou 		ret = dfu->read_medium(dfu, 0, buf, &dfu->r_left);
221*ea2453d5SPantelis Antoniou 		if (ret != 0) {
222*ea2453d5SPantelis Antoniou 			debug("%s: failed to get r_left\n", __func__);
223*ea2453d5SPantelis Antoniou 			return ret;
224f22b11c1SLukasz Majewski 		}
225f22b11c1SLukasz Majewski 
226*ea2453d5SPantelis Antoniou 		debug("%s: %s %ld [B]\n", __func__, dfu->name, dfu->r_left);
227*ea2453d5SPantelis Antoniou 
228*ea2453d5SPantelis Antoniou 		dfu->i_blk_seq_num = 0;
229*ea2453d5SPantelis Antoniou 		dfu->crc = 0;
230*ea2453d5SPantelis Antoniou 		dfu->offset = 0;
231*ea2453d5SPantelis Antoniou 		dfu->i_buf_start = dfu_buf;
232*ea2453d5SPantelis Antoniou 		dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
233*ea2453d5SPantelis Antoniou 		dfu->i_buf = dfu->i_buf_start;
234*ea2453d5SPantelis Antoniou 		dfu->b_left = 0;
235*ea2453d5SPantelis Antoniou 
236*ea2453d5SPantelis Antoniou 		dfu->inited = 1;
237*ea2453d5SPantelis Antoniou 	}
238*ea2453d5SPantelis Antoniou 
239*ea2453d5SPantelis Antoniou 	if (dfu->i_blk_seq_num != blk_seq_num) {
240f22b11c1SLukasz Majewski 		printf("%s: Wrong sequence number! [%d] [%d]\n",
241*ea2453d5SPantelis Antoniou 		       __func__, dfu->i_blk_seq_num, blk_seq_num);
242*ea2453d5SPantelis Antoniou 		return -1;
243*ea2453d5SPantelis Antoniou 	}
244*ea2453d5SPantelis Antoniou 	/* handle rollover */
245*ea2453d5SPantelis Antoniou 	dfu->i_blk_seq_num = (dfu->i_blk_seq_num + 1) & 0xffff;
246*ea2453d5SPantelis Antoniou 
247*ea2453d5SPantelis Antoniou 	ret = dfu_read_buffer_fill(dfu, buf, size);
248*ea2453d5SPantelis Antoniou 	if (ret < 0) {
249*ea2453d5SPantelis Antoniou 		printf("%s: Failed to fill buffer\n", __func__);
250f22b11c1SLukasz Majewski 		return -1;
251f22b11c1SLukasz Majewski 	}
252f22b11c1SLukasz Majewski 
253*ea2453d5SPantelis Antoniou 	if (ret < size) {
254*ea2453d5SPantelis Antoniou 		debug("%s: %s CRC32: 0x%x\n", __func__, dfu->name, dfu->crc);
255*ea2453d5SPantelis Antoniou 		puts("\nUPLOAD ... done\nCtrl+C to exit ...\n");
256f22b11c1SLukasz Majewski 
257*ea2453d5SPantelis Antoniou 		dfu->i_blk_seq_num = 0;
258*ea2453d5SPantelis Antoniou 		dfu->crc = 0;
259*ea2453d5SPantelis Antoniou 		dfu->offset = 0;
260*ea2453d5SPantelis Antoniou 		dfu->i_buf_start = dfu_buf;
261*ea2453d5SPantelis Antoniou 		dfu->i_buf_end = dfu_buf + sizeof(dfu_buf);
262*ea2453d5SPantelis Antoniou 		dfu->i_buf = dfu->i_buf_start;
263*ea2453d5SPantelis Antoniou 		dfu->b_left = 0;
264*ea2453d5SPantelis Antoniou 
265*ea2453d5SPantelis Antoniou 		dfu->inited = 0;
266f22b11c1SLukasz Majewski 	}
267*ea2453d5SPantelis Antoniou 
268f22b11c1SLukasz Majewski 	return ret;
269f22b11c1SLukasz Majewski }
270f22b11c1SLukasz Majewski 
271f22b11c1SLukasz Majewski static int dfu_fill_entity(struct dfu_entity *dfu, char *s, int alt,
272f22b11c1SLukasz Majewski 			    char *interface, int num)
273f22b11c1SLukasz Majewski {
274f22b11c1SLukasz Majewski 	char *st;
275f22b11c1SLukasz Majewski 
276f22b11c1SLukasz Majewski 	debug("%s: %s interface: %s num: %d\n", __func__, s, interface, num);
277f22b11c1SLukasz Majewski 	st = strsep(&s, " ");
278f22b11c1SLukasz Majewski 	strcpy(dfu->name, st);
279f22b11c1SLukasz Majewski 
280f22b11c1SLukasz Majewski 	dfu->dev_num = num;
281f22b11c1SLukasz Majewski 	dfu->alt = alt;
282f22b11c1SLukasz Majewski 
283f22b11c1SLukasz Majewski 	/* Specific for mmc device */
284f22b11c1SLukasz Majewski 	if (strcmp(interface, "mmc") == 0) {
285f22b11c1SLukasz Majewski 		if (dfu_fill_entity_mmc(dfu, s))
286f22b11c1SLukasz Majewski 			return -1;
287f22b11c1SLukasz Majewski 	} else {
288f22b11c1SLukasz Majewski 		printf("%s: Device %s not (yet) supported!\n",
289f22b11c1SLukasz Majewski 		       __func__,  interface);
290f22b11c1SLukasz Majewski 		return -1;
291f22b11c1SLukasz Majewski 	}
292f22b11c1SLukasz Majewski 
293f22b11c1SLukasz Majewski 	return 0;
294f22b11c1SLukasz Majewski }
295f22b11c1SLukasz Majewski 
296f22b11c1SLukasz Majewski void dfu_free_entities(void)
297f22b11c1SLukasz Majewski {
298f22b11c1SLukasz Majewski 	struct dfu_entity *dfu, *p, *t = NULL;
299f22b11c1SLukasz Majewski 
300f22b11c1SLukasz Majewski 	list_for_each_entry_safe_reverse(dfu, p, &dfu_list, list) {
301f22b11c1SLukasz Majewski 		list_del(&dfu->list);
302f22b11c1SLukasz Majewski 		t = dfu;
303f22b11c1SLukasz Majewski 	}
304f22b11c1SLukasz Majewski 	if (t)
305f22b11c1SLukasz Majewski 		free(t);
306f22b11c1SLukasz Majewski 	INIT_LIST_HEAD(&dfu_list);
307f22b11c1SLukasz Majewski }
308f22b11c1SLukasz Majewski 
309f22b11c1SLukasz Majewski int dfu_config_entities(char *env, char *interface, int num)
310f22b11c1SLukasz Majewski {
311f22b11c1SLukasz Majewski 	struct dfu_entity *dfu;
312f22b11c1SLukasz Majewski 	int i, ret;
313f22b11c1SLukasz Majewski 	char *s;
314f22b11c1SLukasz Majewski 
315f22b11c1SLukasz Majewski 	dfu_alt_num = dfu_find_alt_num(env);
316f22b11c1SLukasz Majewski 	debug("%s: dfu_alt_num=%d\n", __func__, dfu_alt_num);
317f22b11c1SLukasz Majewski 
318f22b11c1SLukasz Majewski 	dfu = calloc(sizeof(*dfu), dfu_alt_num);
319f22b11c1SLukasz Majewski 	if (!dfu)
320f22b11c1SLukasz Majewski 		return -1;
321f22b11c1SLukasz Majewski 	for (i = 0; i < dfu_alt_num; i++) {
322f22b11c1SLukasz Majewski 
323f22b11c1SLukasz Majewski 		s = strsep(&env, ";");
324f22b11c1SLukasz Majewski 		ret = dfu_fill_entity(&dfu[i], s, i, interface, num);
325f22b11c1SLukasz Majewski 		if (ret)
326f22b11c1SLukasz Majewski 			return -1;
327f22b11c1SLukasz Majewski 
328f22b11c1SLukasz Majewski 		list_add_tail(&dfu[i].list, &dfu_list);
329f22b11c1SLukasz Majewski 	}
330f22b11c1SLukasz Majewski 
331f22b11c1SLukasz Majewski 	return 0;
332f22b11c1SLukasz Majewski }
333f22b11c1SLukasz Majewski 
334f22b11c1SLukasz Majewski const char *dfu_get_dev_type(enum dfu_device_type t)
335f22b11c1SLukasz Majewski {
336f22b11c1SLukasz Majewski 	const char *dev_t[] = {NULL, "eMMC", "OneNAND", "NAND" };
337f22b11c1SLukasz Majewski 	return dev_t[t];
338f22b11c1SLukasz Majewski }
339f22b11c1SLukasz Majewski 
340f22b11c1SLukasz Majewski const char *dfu_get_layout(enum dfu_layout l)
341f22b11c1SLukasz Majewski {
342f22b11c1SLukasz Majewski 	const char *dfu_layout[] = {NULL, "RAW_ADDR", "FAT", "EXT2",
343f22b11c1SLukasz Majewski 					   "EXT3", "EXT4" };
344f22b11c1SLukasz Majewski 	return dfu_layout[l];
345f22b11c1SLukasz Majewski }
346f22b11c1SLukasz Majewski 
347f22b11c1SLukasz Majewski void dfu_show_entities(void)
348f22b11c1SLukasz Majewski {
349f22b11c1SLukasz Majewski 	struct dfu_entity *dfu;
350f22b11c1SLukasz Majewski 
351f22b11c1SLukasz Majewski 	puts("DFU alt settings list:\n");
352f22b11c1SLukasz Majewski 
353f22b11c1SLukasz Majewski 	list_for_each_entry(dfu, &dfu_list, list) {
354f22b11c1SLukasz Majewski 		printf("dev: %s alt: %d name: %s layout: %s\n",
355f22b11c1SLukasz Majewski 		       dfu_get_dev_type(dfu->dev_type), dfu->alt,
356f22b11c1SLukasz Majewski 		       dfu->name, dfu_get_layout(dfu->layout));
357f22b11c1SLukasz Majewski 	}
358f22b11c1SLukasz Majewski }
359f22b11c1SLukasz Majewski 
360f22b11c1SLukasz Majewski int dfu_get_alt_number(void)
361f22b11c1SLukasz Majewski {
362f22b11c1SLukasz Majewski 	return dfu_alt_num;
363f22b11c1SLukasz Majewski }
364f22b11c1SLukasz Majewski 
365f22b11c1SLukasz Majewski struct dfu_entity *dfu_get_entity(int alt)
366f22b11c1SLukasz Majewski {
367f22b11c1SLukasz Majewski 	struct dfu_entity *dfu;
368f22b11c1SLukasz Majewski 
369f22b11c1SLukasz Majewski 	list_for_each_entry(dfu, &dfu_list, list) {
370f22b11c1SLukasz Majewski 		if (dfu->alt == alt)
371f22b11c1SLukasz Majewski 			return dfu;
372f22b11c1SLukasz Majewski 	}
373f22b11c1SLukasz Majewski 
374f22b11c1SLukasz Majewski 	return NULL;
375f22b11c1SLukasz Majewski }
376