xref: /OK3568_Linux_fs/u-boot/drivers/dfu/dfu_mmc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * dfu.c -- DFU back-end routines
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2012 Samsung Electronics
5*4882a593Smuzhiyun  * author: Lukasz Majewski <l.majewski@samsung.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <common.h>
11*4882a593Smuzhiyun #include <malloc.h>
12*4882a593Smuzhiyun #include <errno.h>
13*4882a593Smuzhiyun #include <div64.h>
14*4882a593Smuzhiyun #include <dfu.h>
15*4882a593Smuzhiyun #include <ext4fs.h>
16*4882a593Smuzhiyun #include <fat.h>
17*4882a593Smuzhiyun #include <mmc.h>
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun static unsigned char *dfu_file_buf;
20*4882a593Smuzhiyun static u64 dfu_file_buf_len;
21*4882a593Smuzhiyun static long dfu_file_buf_filled;
22*4882a593Smuzhiyun 
mmc_block_op(enum dfu_op op,struct dfu_entity * dfu,u64 offset,void * buf,long * len)23*4882a593Smuzhiyun static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
24*4882a593Smuzhiyun 			u64 offset, void *buf, long *len)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun 	struct mmc *mmc;
27*4882a593Smuzhiyun 	u32 blk_start, blk_count, n = 0;
28*4882a593Smuzhiyun 	int ret, part_num_bkp = 0;
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
31*4882a593Smuzhiyun 	if (!mmc) {
32*4882a593Smuzhiyun 		pr_err("Device MMC %d - not found!", dfu->data.mmc.dev_num);
33*4882a593Smuzhiyun 		return -ENODEV;
34*4882a593Smuzhiyun 	}
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	/*
37*4882a593Smuzhiyun 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
38*4882a593Smuzhiyun 	 * this value.
39*4882a593Smuzhiyun 	 */
40*4882a593Smuzhiyun 	*len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	blk_start = dfu->data.mmc.lba_start +
43*4882a593Smuzhiyun 			(u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
44*4882a593Smuzhiyun 	blk_count = *len / dfu->data.mmc.lba_blk_size;
45*4882a593Smuzhiyun 	if (blk_start + blk_count >
46*4882a593Smuzhiyun 			dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
47*4882a593Smuzhiyun 		puts("Request would exceed designated area!\n");
48*4882a593Smuzhiyun 		return -EINVAL;
49*4882a593Smuzhiyun 	}
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	if (dfu->data.mmc.hw_partition >= 0) {
52*4882a593Smuzhiyun 		part_num_bkp = mmc_get_blk_desc(mmc)->hwpart;
53*4882a593Smuzhiyun 		ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
54*4882a593Smuzhiyun 					       dfu->data.mmc.dev_num,
55*4882a593Smuzhiyun 					       dfu->data.mmc.hw_partition);
56*4882a593Smuzhiyun 		if (ret)
57*4882a593Smuzhiyun 			return ret;
58*4882a593Smuzhiyun 	}
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
61*4882a593Smuzhiyun 	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE",
62*4882a593Smuzhiyun 	      dfu->data.mmc.dev_num, blk_start, blk_count, buf);
63*4882a593Smuzhiyun 	switch (op) {
64*4882a593Smuzhiyun 	case DFU_OP_READ:
65*4882a593Smuzhiyun 		n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf);
66*4882a593Smuzhiyun 		break;
67*4882a593Smuzhiyun 	case DFU_OP_WRITE:
68*4882a593Smuzhiyun 		n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count,
69*4882a593Smuzhiyun 			       buf);
70*4882a593Smuzhiyun 		break;
71*4882a593Smuzhiyun 	default:
72*4882a593Smuzhiyun 		pr_err("Operation not supported\n");
73*4882a593Smuzhiyun 	}
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	if (n != blk_count) {
76*4882a593Smuzhiyun 		pr_err("MMC operation failed");
77*4882a593Smuzhiyun 		if (dfu->data.mmc.hw_partition >= 0)
78*4882a593Smuzhiyun 			blk_select_hwpart_devnum(IF_TYPE_MMC,
79*4882a593Smuzhiyun 						 dfu->data.mmc.dev_num,
80*4882a593Smuzhiyun 						 part_num_bkp);
81*4882a593Smuzhiyun 		return -EIO;
82*4882a593Smuzhiyun 	}
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (dfu->data.mmc.hw_partition >= 0) {
85*4882a593Smuzhiyun 		ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
86*4882a593Smuzhiyun 					       dfu->data.mmc.dev_num,
87*4882a593Smuzhiyun 					       part_num_bkp);
88*4882a593Smuzhiyun 		if (ret)
89*4882a593Smuzhiyun 			return ret;
90*4882a593Smuzhiyun 	}
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun 	return 0;
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun 
mmc_file_buffer(struct dfu_entity * dfu,void * buf,long * len)95*4882a593Smuzhiyun static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
96*4882a593Smuzhiyun {
97*4882a593Smuzhiyun 	if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
98*4882a593Smuzhiyun 		dfu_file_buf_len = 0;
99*4882a593Smuzhiyun 		return -EINVAL;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	/* Add to the current buffer. */
103*4882a593Smuzhiyun 	memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
104*4882a593Smuzhiyun 	dfu_file_buf_len += *len;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	return 0;
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun 
mmc_file_op(enum dfu_op op,struct dfu_entity * dfu,void * buf,u64 * len)109*4882a593Smuzhiyun static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
110*4882a593Smuzhiyun 			void *buf, u64 *len)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	const char *fsname, *opname;
113*4882a593Smuzhiyun 	char cmd_buf[DFU_CMD_BUF_SIZE];
114*4882a593Smuzhiyun 	char *str_env;
115*4882a593Smuzhiyun 	int ret;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	switch (dfu->layout) {
118*4882a593Smuzhiyun 	case DFU_FS_FAT:
119*4882a593Smuzhiyun 		fsname = "fat";
120*4882a593Smuzhiyun 		break;
121*4882a593Smuzhiyun 	case DFU_FS_EXT4:
122*4882a593Smuzhiyun 		fsname = "ext4";
123*4882a593Smuzhiyun 		break;
124*4882a593Smuzhiyun 	default:
125*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
126*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
127*4882a593Smuzhiyun 		return -1;
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun 	switch (op) {
131*4882a593Smuzhiyun 	case DFU_OP_READ:
132*4882a593Smuzhiyun 		opname = "load";
133*4882a593Smuzhiyun 		break;
134*4882a593Smuzhiyun 	case DFU_OP_WRITE:
135*4882a593Smuzhiyun 		opname = "write";
136*4882a593Smuzhiyun 		break;
137*4882a593Smuzhiyun 	case DFU_OP_SIZE:
138*4882a593Smuzhiyun 		opname = "size";
139*4882a593Smuzhiyun 		break;
140*4882a593Smuzhiyun 	default:
141*4882a593Smuzhiyun 		return -1;
142*4882a593Smuzhiyun 	}
143*4882a593Smuzhiyun 
144*4882a593Smuzhiyun 	sprintf(cmd_buf, "%s%s mmc %d:%d", fsname, opname,
145*4882a593Smuzhiyun 		dfu->data.mmc.dev, dfu->data.mmc.part);
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	if (op != DFU_OP_SIZE)
148*4882a593Smuzhiyun 		sprintf(cmd_buf + strlen(cmd_buf), " %p", buf);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	if (op == DFU_OP_WRITE)
153*4882a593Smuzhiyun 		sprintf(cmd_buf + strlen(cmd_buf), " %llx", *len);
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	ret = run_command(cmd_buf, 0);
158*4882a593Smuzhiyun 	if (ret) {
159*4882a593Smuzhiyun 		puts("dfu: Read error!\n");
160*4882a593Smuzhiyun 		return ret;
161*4882a593Smuzhiyun 	}
162*4882a593Smuzhiyun 
163*4882a593Smuzhiyun 	if (op != DFU_OP_WRITE) {
164*4882a593Smuzhiyun 		str_env = env_get("filesize");
165*4882a593Smuzhiyun 		if (str_env == NULL) {
166*4882a593Smuzhiyun 			puts("dfu: Wrong file size!\n");
167*4882a593Smuzhiyun 			return -1;
168*4882a593Smuzhiyun 		}
169*4882a593Smuzhiyun 		*len = simple_strtoul(str_env, NULL, 16);
170*4882a593Smuzhiyun 	}
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	return ret;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun 
dfu_write_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)175*4882a593Smuzhiyun int dfu_write_medium_mmc(struct dfu_entity *dfu,
176*4882a593Smuzhiyun 		u64 offset, void *buf, long *len)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun 	int ret = -1;
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	switch (dfu->layout) {
181*4882a593Smuzhiyun 	case DFU_RAW_ADDR:
182*4882a593Smuzhiyun 		ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
183*4882a593Smuzhiyun 		break;
184*4882a593Smuzhiyun 	case DFU_FS_FAT:
185*4882a593Smuzhiyun 	case DFU_FS_EXT4:
186*4882a593Smuzhiyun 		ret = mmc_file_buffer(dfu, buf, len);
187*4882a593Smuzhiyun 		break;
188*4882a593Smuzhiyun 	default:
189*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
190*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
191*4882a593Smuzhiyun 	}
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	return ret;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
dfu_flush_medium_mmc(struct dfu_entity * dfu)196*4882a593Smuzhiyun int dfu_flush_medium_mmc(struct dfu_entity *dfu)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	int ret = 0;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 	if (dfu->layout != DFU_RAW_ADDR) {
201*4882a593Smuzhiyun 		/* Do stuff here. */
202*4882a593Smuzhiyun 		ret = mmc_file_op(DFU_OP_WRITE, dfu, dfu_file_buf,
203*4882a593Smuzhiyun 				&dfu_file_buf_len);
204*4882a593Smuzhiyun 
205*4882a593Smuzhiyun 		/* Now that we're done */
206*4882a593Smuzhiyun 		dfu_file_buf_len = 0;
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 	return ret;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun 
dfu_get_medium_size_mmc(struct dfu_entity * dfu,u64 * size)212*4882a593Smuzhiyun int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	int ret;
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun 	switch (dfu->layout) {
217*4882a593Smuzhiyun 	case DFU_RAW_ADDR:
218*4882a593Smuzhiyun 		*size = dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
219*4882a593Smuzhiyun 		return 0;
220*4882a593Smuzhiyun 	case DFU_FS_FAT:
221*4882a593Smuzhiyun 	case DFU_FS_EXT4:
222*4882a593Smuzhiyun 		dfu_file_buf_filled = -1;
223*4882a593Smuzhiyun 		ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, size);
224*4882a593Smuzhiyun 		if (ret < 0)
225*4882a593Smuzhiyun 			return ret;
226*4882a593Smuzhiyun 		if (*size > CONFIG_SYS_DFU_MAX_FILE_SIZE)
227*4882a593Smuzhiyun 			return -1;
228*4882a593Smuzhiyun 		return 0;
229*4882a593Smuzhiyun 	default:
230*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
231*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
232*4882a593Smuzhiyun 		return -1;
233*4882a593Smuzhiyun 	}
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun 
mmc_file_unbuffer(struct dfu_entity * dfu,u64 offset,void * buf,long * len)236*4882a593Smuzhiyun static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf,
237*4882a593Smuzhiyun 			     long *len)
238*4882a593Smuzhiyun {
239*4882a593Smuzhiyun 	int ret;
240*4882a593Smuzhiyun 	u64 file_len;
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	if (dfu_file_buf_filled == -1) {
243*4882a593Smuzhiyun 		ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len);
244*4882a593Smuzhiyun 		if (ret < 0)
245*4882a593Smuzhiyun 			return ret;
246*4882a593Smuzhiyun 		dfu_file_buf_filled = file_len;
247*4882a593Smuzhiyun 	}
248*4882a593Smuzhiyun 	if (offset + *len > dfu_file_buf_filled)
249*4882a593Smuzhiyun 		return -EINVAL;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	/* Add to the current buffer. */
252*4882a593Smuzhiyun 	memcpy(buf, dfu_file_buf + offset, *len);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	return 0;
255*4882a593Smuzhiyun }
256*4882a593Smuzhiyun 
dfu_read_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)257*4882a593Smuzhiyun int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
258*4882a593Smuzhiyun 		long *len)
259*4882a593Smuzhiyun {
260*4882a593Smuzhiyun 	int ret = -1;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	switch (dfu->layout) {
263*4882a593Smuzhiyun 	case DFU_RAW_ADDR:
264*4882a593Smuzhiyun 		ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
265*4882a593Smuzhiyun 		break;
266*4882a593Smuzhiyun 	case DFU_FS_FAT:
267*4882a593Smuzhiyun 	case DFU_FS_EXT4:
268*4882a593Smuzhiyun 		ret = mmc_file_unbuffer(dfu, offset, buf, len);
269*4882a593Smuzhiyun 		break;
270*4882a593Smuzhiyun 	default:
271*4882a593Smuzhiyun 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
272*4882a593Smuzhiyun 		       dfu_get_layout(dfu->layout));
273*4882a593Smuzhiyun 	}
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 	return ret;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
dfu_free_entity_mmc(struct dfu_entity * dfu)278*4882a593Smuzhiyun void dfu_free_entity_mmc(struct dfu_entity *dfu)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun 	if (dfu_file_buf) {
281*4882a593Smuzhiyun 		free(dfu_file_buf);
282*4882a593Smuzhiyun 		dfu_file_buf = NULL;
283*4882a593Smuzhiyun 	}
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /*
287*4882a593Smuzhiyun  * @param s Parameter string containing space-separated arguments:
288*4882a593Smuzhiyun  *	1st:
289*4882a593Smuzhiyun  *		raw	(raw read/write)
290*4882a593Smuzhiyun  *		fat	(files)
291*4882a593Smuzhiyun  *		ext4	(^)
292*4882a593Smuzhiyun  *		part	(partition image)
293*4882a593Smuzhiyun  *	2nd and 3rd:
294*4882a593Smuzhiyun  *		lba_start and lba_size, for raw write
295*4882a593Smuzhiyun  *		mmc_dev and mmc_part, for filesystems and part
296*4882a593Smuzhiyun  *	4th (optional):
297*4882a593Smuzhiyun  *		mmcpart <num> (access to HW eMMC partitions)
298*4882a593Smuzhiyun  */
dfu_fill_entity_mmc(struct dfu_entity * dfu,char * devstr,char * s)299*4882a593Smuzhiyun int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
300*4882a593Smuzhiyun {
301*4882a593Smuzhiyun 	const char *entity_type;
302*4882a593Smuzhiyun 	size_t second_arg;
303*4882a593Smuzhiyun 	size_t third_arg;
304*4882a593Smuzhiyun 
305*4882a593Smuzhiyun 	struct mmc *mmc;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	const char *argv[3];
308*4882a593Smuzhiyun 	const char **parg = argv;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	dfu->data.mmc.dev_num = simple_strtoul(devstr, NULL, 10);
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
313*4882a593Smuzhiyun 		*parg = strsep(&s, " ");
314*4882a593Smuzhiyun 		if (*parg == NULL) {
315*4882a593Smuzhiyun 			pr_err("Invalid number of arguments.\n");
316*4882a593Smuzhiyun 			return -ENODEV;
317*4882a593Smuzhiyun 		}
318*4882a593Smuzhiyun 	}
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	entity_type = argv[0];
321*4882a593Smuzhiyun 	/*
322*4882a593Smuzhiyun 	 * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
323*4882a593Smuzhiyun 	 * with default 10.
324*4882a593Smuzhiyun 	 */
325*4882a593Smuzhiyun 	second_arg = simple_strtoul(argv[1], NULL, 0);
326*4882a593Smuzhiyun 	third_arg = simple_strtoul(argv[2], NULL, 0);
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
329*4882a593Smuzhiyun 	if (mmc == NULL) {
330*4882a593Smuzhiyun 		pr_err("Couldn't find MMC device no. %d.\n",
331*4882a593Smuzhiyun 		      dfu->data.mmc.dev_num);
332*4882a593Smuzhiyun 		return -ENODEV;
333*4882a593Smuzhiyun 	}
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun 	if (mmc_init(mmc)) {
336*4882a593Smuzhiyun 		pr_err("Couldn't init MMC device.\n");
337*4882a593Smuzhiyun 		return -ENODEV;
338*4882a593Smuzhiyun 	}
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	dfu->data.mmc.hw_partition = -EINVAL;
341*4882a593Smuzhiyun 	if (!strcmp(entity_type, "raw")) {
342*4882a593Smuzhiyun 		dfu->layout			= DFU_RAW_ADDR;
343*4882a593Smuzhiyun 		dfu->data.mmc.lba_start		= second_arg;
344*4882a593Smuzhiyun 		dfu->data.mmc.lba_size		= third_arg;
345*4882a593Smuzhiyun 		dfu->data.mmc.lba_blk_size	= mmc->read_bl_len;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 		/*
348*4882a593Smuzhiyun 		 * Check for an extra entry at dfu_alt_info env variable
349*4882a593Smuzhiyun 		 * specifying the mmc HW defined partition number
350*4882a593Smuzhiyun 		 */
351*4882a593Smuzhiyun 		if (s)
352*4882a593Smuzhiyun 			if (!strcmp(strsep(&s, " "), "mmcpart"))
353*4882a593Smuzhiyun 				dfu->data.mmc.hw_partition =
354*4882a593Smuzhiyun 					simple_strtoul(s, NULL, 0);
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	} else if (!strcmp(entity_type, "part")) {
357*4882a593Smuzhiyun 		disk_partition_t partinfo;
358*4882a593Smuzhiyun 		struct blk_desc *blk_dev = mmc_get_blk_desc(mmc);
359*4882a593Smuzhiyun 		int mmcdev = second_arg;
360*4882a593Smuzhiyun 		int mmcpart = third_arg;
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun 		if (part_get_info(blk_dev, mmcpart, &partinfo) != 0) {
363*4882a593Smuzhiyun 			pr_err("Couldn't find part #%d on mmc device #%d\n",
364*4882a593Smuzhiyun 			      mmcpart, mmcdev);
365*4882a593Smuzhiyun 			return -ENODEV;
366*4882a593Smuzhiyun 		}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 		dfu->layout			= DFU_RAW_ADDR;
369*4882a593Smuzhiyun 		dfu->data.mmc.lba_start		= partinfo.start;
370*4882a593Smuzhiyun 		dfu->data.mmc.lba_size		= partinfo.size;
371*4882a593Smuzhiyun 		dfu->data.mmc.lba_blk_size	= partinfo.blksz;
372*4882a593Smuzhiyun 	} else if (!strcmp(entity_type, "fat")) {
373*4882a593Smuzhiyun 		dfu->layout = DFU_FS_FAT;
374*4882a593Smuzhiyun 	} else if (!strcmp(entity_type, "ext4")) {
375*4882a593Smuzhiyun 		dfu->layout = DFU_FS_EXT4;
376*4882a593Smuzhiyun 	} else {
377*4882a593Smuzhiyun 		pr_err("Memory layout (%s) not supported!\n", entity_type);
378*4882a593Smuzhiyun 		return -ENODEV;
379*4882a593Smuzhiyun 	}
380*4882a593Smuzhiyun 
381*4882a593Smuzhiyun 	/* if it's NOT a raw write */
382*4882a593Smuzhiyun 	if (strcmp(entity_type, "raw")) {
383*4882a593Smuzhiyun 		dfu->data.mmc.dev = second_arg;
384*4882a593Smuzhiyun 		dfu->data.mmc.part = third_arg;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	dfu->dev_type = DFU_DEV_MMC;
388*4882a593Smuzhiyun 	dfu->get_medium_size = dfu_get_medium_size_mmc;
389*4882a593Smuzhiyun 	dfu->read_medium = dfu_read_medium_mmc;
390*4882a593Smuzhiyun 	dfu->write_medium = dfu_write_medium_mmc;
391*4882a593Smuzhiyun 	dfu->flush_medium = dfu_flush_medium_mmc;
392*4882a593Smuzhiyun 	dfu->inited = 0;
393*4882a593Smuzhiyun 	dfu->free_entity = dfu_free_entity_mmc;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	/* Check if file buffer is ready */
396*4882a593Smuzhiyun 	if (!dfu_file_buf) {
397*4882a593Smuzhiyun 		dfu_file_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
398*4882a593Smuzhiyun 					CONFIG_SYS_DFU_MAX_FILE_SIZE);
399*4882a593Smuzhiyun 		if (!dfu_file_buf) {
400*4882a593Smuzhiyun 			pr_err("Could not memalign 0x%x bytes",
401*4882a593Smuzhiyun 			      CONFIG_SYS_DFU_MAX_FILE_SIZE);
402*4882a593Smuzhiyun 			return -ENOMEM;
403*4882a593Smuzhiyun 		}
404*4882a593Smuzhiyun 	}
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun 	return 0;
407*4882a593Smuzhiyun }
408