xref: /openbmc/u-boot/drivers/dfu/dfu_mmc.c (revision 1f92c074cbb53debc7ad31073dc7895d8a2aa44e)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2cb383cd2SLukasz Majewski /*
3cb383cd2SLukasz Majewski  * dfu.c -- DFU back-end routines
4cb383cd2SLukasz Majewski  *
5cb383cd2SLukasz Majewski  * Copyright (C) 2012 Samsung Electronics
6cb383cd2SLukasz Majewski  * author: Lukasz Majewski <l.majewski@samsung.com>
7cb383cd2SLukasz Majewski  */
8cb383cd2SLukasz Majewski 
9cb383cd2SLukasz Majewski #include <common.h>
10cb383cd2SLukasz Majewski #include <malloc.h>
111b6ca18bSPantelis Antoniou #include <errno.h>
12ea2453d5SPantelis Antoniou #include <div64.h>
13cb383cd2SLukasz Majewski #include <dfu.h>
140e285b50SStephen Warren #include <ext4fs.h>
150e285b50SStephen Warren #include <fat.h>
167d0b605aSŁukasz Majewski #include <mmc.h>
17cb383cd2SLukasz Majewski 
1841ac233cSPrzemyslaw Marczak static unsigned char *dfu_file_buf;
1915970d87SPatrick Delaunay static u64 dfu_file_buf_len;
20411c5e57SStephen Warren static long dfu_file_buf_filled;
21ea2453d5SPantelis Antoniou 
mmc_block_op(enum dfu_op op,struct dfu_entity * dfu,u64 offset,void * buf,long * len)225a127c84SAfzal Mohammed static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
23ea2453d5SPantelis Antoniou 			u64 offset, void *buf, long *len)
24cb383cd2SLukasz Majewski {
257da6fa27SPrzemyslaw Marczak 	struct mmc *mmc;
267d0b605aSŁukasz Majewski 	u32 blk_start, blk_count, n = 0;
27c8151b4aSLukasz Majewski 	int ret, part_num_bkp = 0;
28cb383cd2SLukasz Majewski 
297da6fa27SPrzemyslaw Marczak 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
307da6fa27SPrzemyslaw Marczak 	if (!mmc) {
319b643e31SMasahiro Yamada 		pr_err("Device MMC %d - not found!", dfu->data.mmc.dev_num);
327da6fa27SPrzemyslaw Marczak 		return -ENODEV;
337da6fa27SPrzemyslaw Marczak 	}
347da6fa27SPrzemyslaw Marczak 
35ea2453d5SPantelis Antoniou 	/*
36ea2453d5SPantelis Antoniou 	 * We must ensure that we work in lba_blk_size chunks, so ALIGN
37ea2453d5SPantelis Antoniou 	 * this value.
38ea2453d5SPantelis Antoniou 	 */
39ea2453d5SPantelis Antoniou 	*len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
40ea2453d5SPantelis Antoniou 
41ea2453d5SPantelis Antoniou 	blk_start = dfu->data.mmc.lba_start +
42ea2453d5SPantelis Antoniou 			(u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
43ea2453d5SPantelis Antoniou 	blk_count = *len / dfu->data.mmc.lba_blk_size;
44ea2453d5SPantelis Antoniou 	if (blk_start + blk_count >
45ea2453d5SPantelis Antoniou 			dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
46ea2453d5SPantelis Antoniou 		puts("Request would exceed designated area!\n");
47ea2453d5SPantelis Antoniou 		return -EINVAL;
48ea2453d5SPantelis Antoniou 	}
49ea2453d5SPantelis Antoniou 
50c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
51797d1b9dSSimon Glass 		part_num_bkp = mmc_get_blk_desc(mmc)->hwpart;
5269f45cd5SSimon Glass 		ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
5369f45cd5SSimon Glass 					       dfu->data.mmc.dev_num,
54873cc1d7SStephen Warren 					       dfu->data.mmc.hw_partition);
55c8151b4aSLukasz Majewski 		if (ret)
56c8151b4aSLukasz Majewski 			return ret;
57c8151b4aSLukasz Majewski 	}
58c8151b4aSLukasz Majewski 
597d0b605aSŁukasz Majewski 	debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
60dd64827eSStephen Warren 	      op == DFU_OP_READ ? "MMC READ" : "MMC WRITE",
61dd64827eSStephen Warren 	      dfu->data.mmc.dev_num, blk_start, blk_count, buf);
627d0b605aSŁukasz Majewski 	switch (op) {
637d0b605aSŁukasz Majewski 	case DFU_OP_READ:
64797d1b9dSSimon Glass 		n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf);
657d0b605aSŁukasz Majewski 		break;
667d0b605aSŁukasz Majewski 	case DFU_OP_WRITE:
67797d1b9dSSimon Glass 		n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count,
68797d1b9dSSimon Glass 			       buf);
697d0b605aSŁukasz Majewski 		break;
707d0b605aSŁukasz Majewski 	default:
719b643e31SMasahiro Yamada 		pr_err("Operation not supported\n");
727d0b605aSŁukasz Majewski 	}
73cb383cd2SLukasz Majewski 
747d0b605aSŁukasz Majewski 	if (n != blk_count) {
759b643e31SMasahiro Yamada 		pr_err("MMC operation failed");
76c8151b4aSLukasz Majewski 		if (dfu->data.mmc.hw_partition >= 0)
7769f45cd5SSimon Glass 			blk_select_hwpart_devnum(IF_TYPE_MMC,
7869f45cd5SSimon Glass 						 dfu->data.mmc.dev_num,
7969f45cd5SSimon Glass 						 part_num_bkp);
807d0b605aSŁukasz Majewski 		return -EIO;
817d0b605aSŁukasz Majewski 	}
827d0b605aSŁukasz Majewski 
83c8151b4aSLukasz Majewski 	if (dfu->data.mmc.hw_partition >= 0) {
8469f45cd5SSimon Glass 		ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
8569f45cd5SSimon Glass 					       dfu->data.mmc.dev_num,
8669f45cd5SSimon Glass 					       part_num_bkp);
87c8151b4aSLukasz Majewski 		if (ret)
88c8151b4aSLukasz Majewski 			return ret;
89c8151b4aSLukasz Majewski 	}
90c8151b4aSLukasz Majewski 
917d0b605aSŁukasz Majewski 	return 0;
92cb383cd2SLukasz Majewski }
93cb383cd2SLukasz Majewski 
mmc_file_buffer(struct dfu_entity * dfu,void * buf,long * len)94ea2453d5SPantelis Antoniou static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
95cb383cd2SLukasz Majewski {
96ea2453d5SPantelis Antoniou 	if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
97ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
98ea2453d5SPantelis Antoniou 		return -EINVAL;
99cb383cd2SLukasz Majewski 	}
100cb383cd2SLukasz Majewski 
101ea2453d5SPantelis Antoniou 	/* Add to the current buffer. */
102ea2453d5SPantelis Antoniou 	memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
103ea2453d5SPantelis Antoniou 	dfu_file_buf_len += *len;
104ea2453d5SPantelis Antoniou 
105ea2453d5SPantelis Antoniou 	return 0;
106cb383cd2SLukasz Majewski }
107cb383cd2SLukasz Majewski 
mmc_file_op(enum dfu_op op,struct dfu_entity * dfu,void * buf,u64 * len)1085a127c84SAfzal Mohammed static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
10915970d87SPatrick Delaunay 			void *buf, u64 *len)
110cb383cd2SLukasz Majewski {
111*1f92c074SSimon Goldschmidt 	char dev_part_str[8];
112cb383cd2SLukasz Majewski 	int ret;
113*1f92c074SSimon Goldschmidt 	int fstype;
114*1f92c074SSimon Goldschmidt 	loff_t size = 0;
115cb383cd2SLukasz Majewski 
11643e66272SŁukasz Majewski 	switch (dfu->layout) {
11743e66272SŁukasz Majewski 	case DFU_FS_FAT:
118*1f92c074SSimon Goldschmidt 		fstype = FS_TYPE_FAT;
11943e66272SŁukasz Majewski 		break;
12043e66272SŁukasz Majewski 	case DFU_FS_EXT4:
121*1f92c074SSimon Goldschmidt 		fstype = FS_TYPE_EXT;
12243e66272SŁukasz Majewski 		break;
12343e66272SŁukasz Majewski 	default:
12443e66272SŁukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
12543e66272SŁukasz Majewski 		       dfu_get_layout(dfu->layout));
126ea2453d5SPantelis Antoniou 		return -1;
12743e66272SŁukasz Majewski 	}
128cb383cd2SLukasz Majewski 
129*1f92c074SSimon Goldschmidt 	snprintf(dev_part_str, sizeof(dev_part_str), "%d:%d",
1300e285b50SStephen Warren 		 dfu->data.mmc.dev, dfu->data.mmc.part);
1310e285b50SStephen Warren 
132*1f92c074SSimon Goldschmidt 	ret = fs_set_blk_dev("mmc", dev_part_str, fstype);
133cb383cd2SLukasz Majewski 	if (ret) {
134*1f92c074SSimon Goldschmidt 		puts("dfu: fs_set_blk_dev error!\n");
135cb383cd2SLukasz Majewski 		return ret;
136cb383cd2SLukasz Majewski 	}
137cb383cd2SLukasz Majewski 
138*1f92c074SSimon Goldschmidt 	switch (op) {
139*1f92c074SSimon Goldschmidt 	case DFU_OP_READ:
140*1f92c074SSimon Goldschmidt 		ret = fs_read(dfu->name, (size_t)buf, 0, 0, &size);
141*1f92c074SSimon Goldschmidt 		if (ret) {
142*1f92c074SSimon Goldschmidt 			puts("dfu: fs_read error!\n");
143*1f92c074SSimon Goldschmidt 			return ret;
144cb383cd2SLukasz Majewski 		}
145*1f92c074SSimon Goldschmidt 		*len = size;
146*1f92c074SSimon Goldschmidt 		break;
147*1f92c074SSimon Goldschmidt 	case DFU_OP_WRITE:
148*1f92c074SSimon Goldschmidt 		ret = fs_write(dfu->name, (size_t)buf, 0, *len, &size);
149*1f92c074SSimon Goldschmidt 		if (ret) {
150*1f92c074SSimon Goldschmidt 			puts("dfu: fs_write error!\n");
151*1f92c074SSimon Goldschmidt 			return ret;
152*1f92c074SSimon Goldschmidt 		}
153*1f92c074SSimon Goldschmidt 		break;
154*1f92c074SSimon Goldschmidt 	case DFU_OP_SIZE:
155*1f92c074SSimon Goldschmidt 		ret = fs_size(dfu->name, &size);
156*1f92c074SSimon Goldschmidt 		if (ret) {
157*1f92c074SSimon Goldschmidt 			puts("dfu: fs_size error!\n");
158*1f92c074SSimon Goldschmidt 			return ret;
159*1f92c074SSimon Goldschmidt 		}
160*1f92c074SSimon Goldschmidt 		*len = size;
161*1f92c074SSimon Goldschmidt 		break;
162*1f92c074SSimon Goldschmidt 	default:
163*1f92c074SSimon Goldschmidt 		return -1;
164cb383cd2SLukasz Majewski 	}
165cb383cd2SLukasz Majewski 
166cb383cd2SLukasz Majewski 	return ret;
167cb383cd2SLukasz Majewski }
168cb383cd2SLukasz Majewski 
dfu_write_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)169ea2453d5SPantelis Antoniou int dfu_write_medium_mmc(struct dfu_entity *dfu,
170ea2453d5SPantelis Antoniou 		u64 offset, void *buf, long *len)
171cb383cd2SLukasz Majewski {
172cb383cd2SLukasz Majewski 	int ret = -1;
173cb383cd2SLukasz Majewski 
174cb383cd2SLukasz Majewski 	switch (dfu->layout) {
175cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
176ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
177cb383cd2SLukasz Majewski 		break;
178cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
17943e66272SŁukasz Majewski 	case DFU_FS_EXT4:
180ea2453d5SPantelis Antoniou 		ret = mmc_file_buffer(dfu, buf, len);
181cb383cd2SLukasz Majewski 		break;
182cb383cd2SLukasz Majewski 	default:
183cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
184cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
185cb383cd2SLukasz Majewski 	}
186cb383cd2SLukasz Majewski 
187cb383cd2SLukasz Majewski 	return ret;
188cb383cd2SLukasz Majewski }
189cb383cd2SLukasz Majewski 
dfu_flush_medium_mmc(struct dfu_entity * dfu)190ea2453d5SPantelis Antoniou int dfu_flush_medium_mmc(struct dfu_entity *dfu)
191ea2453d5SPantelis Antoniou {
192ea2453d5SPantelis Antoniou 	int ret = 0;
193ea2453d5SPantelis Antoniou 
194ea2453d5SPantelis Antoniou 	if (dfu->layout != DFU_RAW_ADDR) {
195ea2453d5SPantelis Antoniou 		/* Do stuff here. */
19641ac233cSPrzemyslaw Marczak 		ret = mmc_file_op(DFU_OP_WRITE, dfu, dfu_file_buf,
197ea2453d5SPantelis Antoniou 				&dfu_file_buf_len);
198ea2453d5SPantelis Antoniou 
199ea2453d5SPantelis Antoniou 		/* Now that we're done */
200ea2453d5SPantelis Antoniou 		dfu_file_buf_len = 0;
201ea2453d5SPantelis Antoniou 	}
202ea2453d5SPantelis Antoniou 
203ea2453d5SPantelis Antoniou 	return ret;
204ea2453d5SPantelis Antoniou }
205ea2453d5SPantelis Antoniou 
dfu_get_medium_size_mmc(struct dfu_entity * dfu,u64 * size)20615970d87SPatrick Delaunay int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size)
2070e285b50SStephen Warren {
2080e285b50SStephen Warren 	int ret;
2090e285b50SStephen Warren 
2100e285b50SStephen Warren 	switch (dfu->layout) {
2110e285b50SStephen Warren 	case DFU_RAW_ADDR:
2124de51201SPatrick Delaunay 		*size = dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
2134de51201SPatrick Delaunay 		return 0;
2140e285b50SStephen Warren 	case DFU_FS_FAT:
2150e285b50SStephen Warren 	case DFU_FS_EXT4:
216411c5e57SStephen Warren 		dfu_file_buf_filled = -1;
2174de51201SPatrick Delaunay 		ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, size);
2180e285b50SStephen Warren 		if (ret < 0)
2190e285b50SStephen Warren 			return ret;
2204de51201SPatrick Delaunay 		if (*size > CONFIG_SYS_DFU_MAX_FILE_SIZE)
221411c5e57SStephen Warren 			return -1;
2224de51201SPatrick Delaunay 		return 0;
2230e285b50SStephen Warren 	default:
2240e285b50SStephen Warren 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
2250e285b50SStephen Warren 		       dfu_get_layout(dfu->layout));
2260e285b50SStephen Warren 		return -1;
2270e285b50SStephen Warren 	}
2280e285b50SStephen Warren }
2290e285b50SStephen Warren 
mmc_file_unbuffer(struct dfu_entity * dfu,u64 offset,void * buf,long * len)230411c5e57SStephen Warren static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf,
231411c5e57SStephen Warren 			     long *len)
232411c5e57SStephen Warren {
233411c5e57SStephen Warren 	int ret;
23415970d87SPatrick Delaunay 	u64 file_len;
235411c5e57SStephen Warren 
236411c5e57SStephen Warren 	if (dfu_file_buf_filled == -1) {
237411c5e57SStephen Warren 		ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len);
238411c5e57SStephen Warren 		if (ret < 0)
239411c5e57SStephen Warren 			return ret;
240411c5e57SStephen Warren 		dfu_file_buf_filled = file_len;
241411c5e57SStephen Warren 	}
242411c5e57SStephen Warren 	if (offset + *len > dfu_file_buf_filled)
243411c5e57SStephen Warren 		return -EINVAL;
244411c5e57SStephen Warren 
245411c5e57SStephen Warren 	/* Add to the current buffer. */
246411c5e57SStephen Warren 	memcpy(buf, dfu_file_buf + offset, *len);
247411c5e57SStephen Warren 
248411c5e57SStephen Warren 	return 0;
249411c5e57SStephen Warren }
250411c5e57SStephen Warren 
dfu_read_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)251ea2453d5SPantelis Antoniou int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
252ea2453d5SPantelis Antoniou 		long *len)
253cb383cd2SLukasz Majewski {
254cb383cd2SLukasz Majewski 	int ret = -1;
255cb383cd2SLukasz Majewski 
256cb383cd2SLukasz Majewski 	switch (dfu->layout) {
257cb383cd2SLukasz Majewski 	case DFU_RAW_ADDR:
258ea2453d5SPantelis Antoniou 		ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
259cb383cd2SLukasz Majewski 		break;
260cb383cd2SLukasz Majewski 	case DFU_FS_FAT:
26143e66272SŁukasz Majewski 	case DFU_FS_EXT4:
262411c5e57SStephen Warren 		ret = mmc_file_unbuffer(dfu, offset, buf, len);
263cb383cd2SLukasz Majewski 		break;
264cb383cd2SLukasz Majewski 	default:
265cb383cd2SLukasz Majewski 		printf("%s: Layout (%s) not (yet) supported!\n", __func__,
266cb383cd2SLukasz Majewski 		       dfu_get_layout(dfu->layout));
267cb383cd2SLukasz Majewski 	}
268cb383cd2SLukasz Majewski 
269cb383cd2SLukasz Majewski 	return ret;
270cb383cd2SLukasz Majewski }
271cb383cd2SLukasz Majewski 
dfu_free_entity_mmc(struct dfu_entity * dfu)27241ac233cSPrzemyslaw Marczak void dfu_free_entity_mmc(struct dfu_entity *dfu)
27341ac233cSPrzemyslaw Marczak {
27441ac233cSPrzemyslaw Marczak 	if (dfu_file_buf) {
27541ac233cSPrzemyslaw Marczak 		free(dfu_file_buf);
27641ac233cSPrzemyslaw Marczak 		dfu_file_buf = NULL;
27741ac233cSPrzemyslaw Marczak 	}
27841ac233cSPrzemyslaw Marczak }
27941ac233cSPrzemyslaw Marczak 
280711b931fSMateusz Zalega /*
281711b931fSMateusz Zalega  * @param s Parameter string containing space-separated arguments:
282711b931fSMateusz Zalega  *	1st:
283711b931fSMateusz Zalega  *		raw	(raw read/write)
284711b931fSMateusz Zalega  *		fat	(files)
285711b931fSMateusz Zalega  *		ext4	(^)
286711b931fSMateusz Zalega  *		part	(partition image)
287711b931fSMateusz Zalega  *	2nd and 3rd:
288711b931fSMateusz Zalega  *		lba_start and lba_size, for raw write
289711b931fSMateusz Zalega  *		mmc_dev and mmc_part, for filesystems and part
290c8151b4aSLukasz Majewski  *	4th (optional):
291c8151b4aSLukasz Majewski  *		mmcpart <num> (access to HW eMMC partitions)
292711b931fSMateusz Zalega  */
dfu_fill_entity_mmc(struct dfu_entity * dfu,char * devstr,char * s)293dd64827eSStephen Warren int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
294cb383cd2SLukasz Majewski {
295711b931fSMateusz Zalega 	const char *entity_type;
296711b931fSMateusz Zalega 	size_t second_arg;
297711b931fSMateusz Zalega 	size_t third_arg;
298711b931fSMateusz Zalega 
2991b6ca18bSPantelis Antoniou 	struct mmc *mmc;
300711b931fSMateusz Zalega 
301711b931fSMateusz Zalega 	const char *argv[3];
302711b931fSMateusz Zalega 	const char **parg = argv;
303711b931fSMateusz Zalega 
304dd64827eSStephen Warren 	dfu->data.mmc.dev_num = simple_strtoul(devstr, NULL, 10);
305dd64827eSStephen Warren 
306711b931fSMateusz Zalega 	for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
307711b931fSMateusz Zalega 		*parg = strsep(&s, " ");
308711b931fSMateusz Zalega 		if (*parg == NULL) {
3099b643e31SMasahiro Yamada 			pr_err("Invalid number of arguments.\n");
310711b931fSMateusz Zalega 			return -ENODEV;
311711b931fSMateusz Zalega 		}
312711b931fSMateusz Zalega 	}
313711b931fSMateusz Zalega 
314711b931fSMateusz Zalega 	entity_type = argv[0];
315b7d4259aSMateusz Zalega 	/*
316b7d4259aSMateusz Zalega 	 * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
317b7d4259aSMateusz Zalega 	 * with default 10.
318b7d4259aSMateusz Zalega 	 */
319b7d4259aSMateusz Zalega 	second_arg = simple_strtoul(argv[1], NULL, 0);
320b7d4259aSMateusz Zalega 	third_arg = simple_strtoul(argv[2], NULL, 0);
321711b931fSMateusz Zalega 
322dd64827eSStephen Warren 	mmc = find_mmc_device(dfu->data.mmc.dev_num);
323711b931fSMateusz Zalega 	if (mmc == NULL) {
3249b643e31SMasahiro Yamada 		pr_err("Couldn't find MMC device no. %d.\n",
325dd64827eSStephen Warren 		      dfu->data.mmc.dev_num);
326711b931fSMateusz Zalega 		return -ENODEV;
327711b931fSMateusz Zalega 	}
328711b931fSMateusz Zalega 
329711b931fSMateusz Zalega 	if (mmc_init(mmc)) {
3309b643e31SMasahiro Yamada 		pr_err("Couldn't init MMC device.\n");
331711b931fSMateusz Zalega 		return -ENODEV;
332711b931fSMateusz Zalega 	}
333711b931fSMateusz Zalega 
334c8151b4aSLukasz Majewski 	dfu->data.mmc.hw_partition = -EINVAL;
335711b931fSMateusz Zalega 	if (!strcmp(entity_type, "raw")) {
336711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
337711b931fSMateusz Zalega 		dfu->data.mmc.lba_start		= second_arg;
338711b931fSMateusz Zalega 		dfu->data.mmc.lba_size		= third_arg;
339711b931fSMateusz Zalega 		dfu->data.mmc.lba_blk_size	= mmc->read_bl_len;
340c8151b4aSLukasz Majewski 
341c8151b4aSLukasz Majewski 		/*
342c8151b4aSLukasz Majewski 		 * Check for an extra entry at dfu_alt_info env variable
343c8151b4aSLukasz Majewski 		 * specifying the mmc HW defined partition number
344c8151b4aSLukasz Majewski 		 */
345c8151b4aSLukasz Majewski 		if (s)
346c8151b4aSLukasz Majewski 			if (!strcmp(strsep(&s, " "), "mmcpart"))
347c8151b4aSLukasz Majewski 				dfu->data.mmc.hw_partition =
348c8151b4aSLukasz Majewski 					simple_strtoul(s, NULL, 0);
349c8151b4aSLukasz Majewski 
350711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "part")) {
3511b6ca18bSPantelis Antoniou 		disk_partition_t partinfo;
352797d1b9dSSimon Glass 		struct blk_desc *blk_dev = mmc_get_blk_desc(mmc);
353711b931fSMateusz Zalega 		int mmcdev = second_arg;
354711b931fSMateusz Zalega 		int mmcpart = third_arg;
355cb383cd2SLukasz Majewski 
3563e8bd469SSimon Glass 		if (part_get_info(blk_dev, mmcpart, &partinfo) != 0) {
3579b643e31SMasahiro Yamada 			pr_err("Couldn't find part #%d on mmc device #%d\n",
358711b931fSMateusz Zalega 			      mmcpart, mmcdev);
3591b6ca18bSPantelis Antoniou 			return -ENODEV;
3601b6ca18bSPantelis Antoniou 		}
3611b6ca18bSPantelis Antoniou 
362711b931fSMateusz Zalega 		dfu->layout			= DFU_RAW_ADDR;
3631b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_start		= partinfo.start;
3641b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_size		= partinfo.size;
3651b6ca18bSPantelis Antoniou 		dfu->data.mmc.lba_blk_size	= partinfo.blksz;
366711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "fat")) {
367711b931fSMateusz Zalega 		dfu->layout = DFU_FS_FAT;
368711b931fSMateusz Zalega 	} else if (!strcmp(entity_type, "ext4")) {
369711b931fSMateusz Zalega 		dfu->layout = DFU_FS_EXT4;
370cb383cd2SLukasz Majewski 	} else {
3719b643e31SMasahiro Yamada 		pr_err("Memory layout (%s) not supported!\n", entity_type);
3721b6ca18bSPantelis Antoniou 		return -ENODEV;
373cb383cd2SLukasz Majewski 	}
374cb383cd2SLukasz Majewski 
375711b931fSMateusz Zalega 	/* if it's NOT a raw write */
376711b931fSMateusz Zalega 	if (strcmp(entity_type, "raw")) {
377711b931fSMateusz Zalega 		dfu->data.mmc.dev = second_arg;
378711b931fSMateusz Zalega 		dfu->data.mmc.part = third_arg;
37943e66272SŁukasz Majewski 	}
38043e66272SŁukasz Majewski 
381711b931fSMateusz Zalega 	dfu->dev_type = DFU_DEV_MMC;
3820e285b50SStephen Warren 	dfu->get_medium_size = dfu_get_medium_size_mmc;
383cb383cd2SLukasz Majewski 	dfu->read_medium = dfu_read_medium_mmc;
384cb383cd2SLukasz Majewski 	dfu->write_medium = dfu_write_medium_mmc;
385ea2453d5SPantelis Antoniou 	dfu->flush_medium = dfu_flush_medium_mmc;
386ea2453d5SPantelis Antoniou 	dfu->inited = 0;
38741ac233cSPrzemyslaw Marczak 	dfu->free_entity = dfu_free_entity_mmc;
38841ac233cSPrzemyslaw Marczak 
38941ac233cSPrzemyslaw Marczak 	/* Check if file buffer is ready */
39041ac233cSPrzemyslaw Marczak 	if (!dfu_file_buf) {
39141ac233cSPrzemyslaw Marczak 		dfu_file_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
39241ac233cSPrzemyslaw Marczak 					CONFIG_SYS_DFU_MAX_FILE_SIZE);
39341ac233cSPrzemyslaw Marczak 		if (!dfu_file_buf) {
3949b643e31SMasahiro Yamada 			pr_err("Could not memalign 0x%x bytes",
39541ac233cSPrzemyslaw Marczak 			      CONFIG_SYS_DFU_MAX_FILE_SIZE);
39641ac233cSPrzemyslaw Marczak 			return -ENOMEM;
39741ac233cSPrzemyslaw Marczak 		}
39841ac233cSPrzemyslaw Marczak 	}
399cb383cd2SLukasz Majewski 
400cb383cd2SLukasz Majewski 	return 0;
401cb383cd2SLukasz Majewski }
402