1cb383cd2SLukasz Majewski /*
2cb383cd2SLukasz Majewski * dfu.c -- DFU back-end routines
3cb383cd2SLukasz Majewski *
4cb383cd2SLukasz Majewski * Copyright (C) 2012 Samsung Electronics
5cb383cd2SLukasz Majewski * author: Lukasz Majewski <l.majewski@samsung.com>
6cb383cd2SLukasz Majewski *
71a459660SWolfgang Denk * SPDX-License-Identifier: GPL-2.0+
8cb383cd2SLukasz Majewski */
9cb383cd2SLukasz Majewski
10cb383cd2SLukasz Majewski #include <common.h>
11cb383cd2SLukasz Majewski #include <malloc.h>
121b6ca18bSPantelis Antoniou #include <errno.h>
13ea2453d5SPantelis Antoniou #include <div64.h>
14cb383cd2SLukasz Majewski #include <dfu.h>
150e285b50SStephen Warren #include <ext4fs.h>
160e285b50SStephen Warren #include <fat.h>
177d0b605aSŁukasz Majewski #include <mmc.h>
18cb383cd2SLukasz Majewski
1941ac233cSPrzemyslaw Marczak static unsigned char *dfu_file_buf;
2015970d87SPatrick Delaunay static u64 dfu_file_buf_len;
21411c5e57SStephen Warren static long dfu_file_buf_filled;
22ea2453d5SPantelis Antoniou
mmc_block_op(enum dfu_op op,struct dfu_entity * dfu,u64 offset,void * buf,long * len)235a127c84SAfzal Mohammed static int mmc_block_op(enum dfu_op op, struct dfu_entity *dfu,
24ea2453d5SPantelis Antoniou u64 offset, void *buf, long *len)
25cb383cd2SLukasz Majewski {
267da6fa27SPrzemyslaw Marczak struct mmc *mmc;
277d0b605aSŁukasz Majewski u32 blk_start, blk_count, n = 0;
28c8151b4aSLukasz Majewski int ret, part_num_bkp = 0;
29cb383cd2SLukasz Majewski
307da6fa27SPrzemyslaw Marczak mmc = find_mmc_device(dfu->data.mmc.dev_num);
317da6fa27SPrzemyslaw Marczak if (!mmc) {
32*90aa625cSMasahiro Yamada pr_err("Device MMC %d - not found!", dfu->data.mmc.dev_num);
337da6fa27SPrzemyslaw Marczak return -ENODEV;
347da6fa27SPrzemyslaw Marczak }
357da6fa27SPrzemyslaw Marczak
36ea2453d5SPantelis Antoniou /*
37ea2453d5SPantelis Antoniou * We must ensure that we work in lba_blk_size chunks, so ALIGN
38ea2453d5SPantelis Antoniou * this value.
39ea2453d5SPantelis Antoniou */
40ea2453d5SPantelis Antoniou *len = ALIGN(*len, dfu->data.mmc.lba_blk_size);
41ea2453d5SPantelis Antoniou
42ea2453d5SPantelis Antoniou blk_start = dfu->data.mmc.lba_start +
43ea2453d5SPantelis Antoniou (u32)lldiv(offset, dfu->data.mmc.lba_blk_size);
44ea2453d5SPantelis Antoniou blk_count = *len / dfu->data.mmc.lba_blk_size;
45ea2453d5SPantelis Antoniou if (blk_start + blk_count >
46ea2453d5SPantelis Antoniou dfu->data.mmc.lba_start + dfu->data.mmc.lba_size) {
47ea2453d5SPantelis Antoniou puts("Request would exceed designated area!\n");
48ea2453d5SPantelis Antoniou return -EINVAL;
49ea2453d5SPantelis Antoniou }
50ea2453d5SPantelis Antoniou
51c8151b4aSLukasz Majewski if (dfu->data.mmc.hw_partition >= 0) {
52797d1b9dSSimon Glass part_num_bkp = mmc_get_blk_desc(mmc)->hwpart;
5369f45cd5SSimon Glass ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
5469f45cd5SSimon Glass dfu->data.mmc.dev_num,
55873cc1d7SStephen Warren dfu->data.mmc.hw_partition);
56c8151b4aSLukasz Majewski if (ret)
57c8151b4aSLukasz Majewski return ret;
58c8151b4aSLukasz Majewski }
59c8151b4aSLukasz Majewski
607d0b605aSŁukasz Majewski debug("%s: %s dev: %d start: %d cnt: %d buf: 0x%p\n", __func__,
61dd64827eSStephen Warren op == DFU_OP_READ ? "MMC READ" : "MMC WRITE",
62dd64827eSStephen Warren dfu->data.mmc.dev_num, blk_start, blk_count, buf);
637d0b605aSŁukasz Majewski switch (op) {
647d0b605aSŁukasz Majewski case DFU_OP_READ:
65797d1b9dSSimon Glass n = blk_dread(mmc_get_blk_desc(mmc), blk_start, blk_count, buf);
667d0b605aSŁukasz Majewski break;
677d0b605aSŁukasz Majewski case DFU_OP_WRITE:
68797d1b9dSSimon Glass n = blk_dwrite(mmc_get_blk_desc(mmc), blk_start, blk_count,
69797d1b9dSSimon Glass buf);
707d0b605aSŁukasz Majewski break;
717d0b605aSŁukasz Majewski default:
72*90aa625cSMasahiro Yamada pr_err("Operation not supported\n");
737d0b605aSŁukasz Majewski }
74cb383cd2SLukasz Majewski
757d0b605aSŁukasz Majewski if (n != blk_count) {
76*90aa625cSMasahiro Yamada pr_err("MMC operation failed");
77c8151b4aSLukasz Majewski if (dfu->data.mmc.hw_partition >= 0)
7869f45cd5SSimon Glass blk_select_hwpart_devnum(IF_TYPE_MMC,
7969f45cd5SSimon Glass dfu->data.mmc.dev_num,
8069f45cd5SSimon Glass part_num_bkp);
817d0b605aSŁukasz Majewski return -EIO;
827d0b605aSŁukasz Majewski }
837d0b605aSŁukasz Majewski
84c8151b4aSLukasz Majewski if (dfu->data.mmc.hw_partition >= 0) {
8569f45cd5SSimon Glass ret = blk_select_hwpart_devnum(IF_TYPE_MMC,
8669f45cd5SSimon Glass dfu->data.mmc.dev_num,
8769f45cd5SSimon Glass part_num_bkp);
88c8151b4aSLukasz Majewski if (ret)
89c8151b4aSLukasz Majewski return ret;
90c8151b4aSLukasz Majewski }
91c8151b4aSLukasz Majewski
927d0b605aSŁukasz Majewski return 0;
93cb383cd2SLukasz Majewski }
94cb383cd2SLukasz Majewski
mmc_file_buffer(struct dfu_entity * dfu,void * buf,long * len)95ea2453d5SPantelis Antoniou static int mmc_file_buffer(struct dfu_entity *dfu, void *buf, long *len)
96cb383cd2SLukasz Majewski {
97ea2453d5SPantelis Antoniou if (dfu_file_buf_len + *len > CONFIG_SYS_DFU_MAX_FILE_SIZE) {
98ea2453d5SPantelis Antoniou dfu_file_buf_len = 0;
99ea2453d5SPantelis Antoniou return -EINVAL;
100cb383cd2SLukasz Majewski }
101cb383cd2SLukasz Majewski
102ea2453d5SPantelis Antoniou /* Add to the current buffer. */
103ea2453d5SPantelis Antoniou memcpy(dfu_file_buf + dfu_file_buf_len, buf, *len);
104ea2453d5SPantelis Antoniou dfu_file_buf_len += *len;
105ea2453d5SPantelis Antoniou
106ea2453d5SPantelis Antoniou return 0;
107cb383cd2SLukasz Majewski }
108cb383cd2SLukasz Majewski
mmc_file_op(enum dfu_op op,struct dfu_entity * dfu,void * buf,u64 * len)1095a127c84SAfzal Mohammed static int mmc_file_op(enum dfu_op op, struct dfu_entity *dfu,
11015970d87SPatrick Delaunay void *buf, u64 *len)
111cb383cd2SLukasz Majewski {
1120e285b50SStephen Warren const char *fsname, *opname;
113cb383cd2SLukasz Majewski char cmd_buf[DFU_CMD_BUF_SIZE];
114cb383cd2SLukasz Majewski char *str_env;
115cb383cd2SLukasz Majewski int ret;
116cb383cd2SLukasz Majewski
11743e66272SŁukasz Majewski switch (dfu->layout) {
11843e66272SŁukasz Majewski case DFU_FS_FAT:
1190e285b50SStephen Warren fsname = "fat";
12043e66272SŁukasz Majewski break;
12143e66272SŁukasz Majewski case DFU_FS_EXT4:
1220e285b50SStephen Warren fsname = "ext4";
12343e66272SŁukasz Majewski break;
12443e66272SŁukasz Majewski default:
12543e66272SŁukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__,
12643e66272SŁukasz Majewski dfu_get_layout(dfu->layout));
127ea2453d5SPantelis Antoniou return -1;
12843e66272SŁukasz Majewski }
129cb383cd2SLukasz Majewski
1300e285b50SStephen Warren switch (op) {
1310e285b50SStephen Warren case DFU_OP_READ:
1320e285b50SStephen Warren opname = "load";
1330e285b50SStephen Warren break;
1340e285b50SStephen Warren case DFU_OP_WRITE:
1350e285b50SStephen Warren opname = "write";
1360e285b50SStephen Warren break;
1370e285b50SStephen Warren case DFU_OP_SIZE:
1380e285b50SStephen Warren opname = "size";
1390e285b50SStephen Warren break;
1400e285b50SStephen Warren default:
1410e285b50SStephen Warren return -1;
1420e285b50SStephen Warren }
1430e285b50SStephen Warren
1440e285b50SStephen Warren sprintf(cmd_buf, "%s%s mmc %d:%d", fsname, opname,
1450e285b50SStephen Warren dfu->data.mmc.dev, dfu->data.mmc.part);
1460e285b50SStephen Warren
1470e285b50SStephen Warren if (op != DFU_OP_SIZE)
148e621c7abSStephen Warren sprintf(cmd_buf + strlen(cmd_buf), " %p", buf);
1490e285b50SStephen Warren
1500e285b50SStephen Warren sprintf(cmd_buf + strlen(cmd_buf), " %s", dfu->name);
1510e285b50SStephen Warren
15217eb1d8fSLukasz Majewski if (op == DFU_OP_WRITE)
15315970d87SPatrick Delaunay sprintf(cmd_buf + strlen(cmd_buf), " %llx", *len);
15417eb1d8fSLukasz Majewski
155cb383cd2SLukasz Majewski debug("%s: %s 0x%p\n", __func__, cmd_buf, cmd_buf);
156cb383cd2SLukasz Majewski
157cb383cd2SLukasz Majewski ret = run_command(cmd_buf, 0);
158cb383cd2SLukasz Majewski if (ret) {
159cb383cd2SLukasz Majewski puts("dfu: Read error!\n");
160cb383cd2SLukasz Majewski return ret;
161cb383cd2SLukasz Majewski }
162cb383cd2SLukasz Majewski
1630e285b50SStephen Warren if (op != DFU_OP_WRITE) {
16400caae6dSSimon Glass str_env = env_get("filesize");
165cb383cd2SLukasz Majewski if (str_env == NULL) {
166cb383cd2SLukasz Majewski puts("dfu: Wrong file size!\n");
167cb383cd2SLukasz Majewski return -1;
168cb383cd2SLukasz Majewski }
169cb383cd2SLukasz Majewski *len = simple_strtoul(str_env, NULL, 16);
170cb383cd2SLukasz Majewski }
171cb383cd2SLukasz Majewski
172cb383cd2SLukasz Majewski return ret;
173cb383cd2SLukasz Majewski }
174cb383cd2SLukasz Majewski
dfu_write_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)175ea2453d5SPantelis Antoniou int dfu_write_medium_mmc(struct dfu_entity *dfu,
176ea2453d5SPantelis Antoniou u64 offset, void *buf, long *len)
177cb383cd2SLukasz Majewski {
178cb383cd2SLukasz Majewski int ret = -1;
179cb383cd2SLukasz Majewski
180cb383cd2SLukasz Majewski switch (dfu->layout) {
181cb383cd2SLukasz Majewski case DFU_RAW_ADDR:
182ea2453d5SPantelis Antoniou ret = mmc_block_op(DFU_OP_WRITE, dfu, offset, buf, len);
183cb383cd2SLukasz Majewski break;
184cb383cd2SLukasz Majewski case DFU_FS_FAT:
18543e66272SŁukasz Majewski case DFU_FS_EXT4:
186ea2453d5SPantelis Antoniou ret = mmc_file_buffer(dfu, buf, len);
187cb383cd2SLukasz Majewski break;
188cb383cd2SLukasz Majewski default:
189cb383cd2SLukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__,
190cb383cd2SLukasz Majewski dfu_get_layout(dfu->layout));
191cb383cd2SLukasz Majewski }
192cb383cd2SLukasz Majewski
193cb383cd2SLukasz Majewski return ret;
194cb383cd2SLukasz Majewski }
195cb383cd2SLukasz Majewski
dfu_flush_medium_mmc(struct dfu_entity * dfu)196ea2453d5SPantelis Antoniou int dfu_flush_medium_mmc(struct dfu_entity *dfu)
197ea2453d5SPantelis Antoniou {
198ea2453d5SPantelis Antoniou int ret = 0;
199ea2453d5SPantelis Antoniou
200ea2453d5SPantelis Antoniou if (dfu->layout != DFU_RAW_ADDR) {
201ea2453d5SPantelis Antoniou /* Do stuff here. */
20241ac233cSPrzemyslaw Marczak ret = mmc_file_op(DFU_OP_WRITE, dfu, dfu_file_buf,
203ea2453d5SPantelis Antoniou &dfu_file_buf_len);
204ea2453d5SPantelis Antoniou
205ea2453d5SPantelis Antoniou /* Now that we're done */
206ea2453d5SPantelis Antoniou dfu_file_buf_len = 0;
207ea2453d5SPantelis Antoniou }
208ea2453d5SPantelis Antoniou
209ea2453d5SPantelis Antoniou return ret;
210ea2453d5SPantelis Antoniou }
211ea2453d5SPantelis Antoniou
dfu_get_medium_size_mmc(struct dfu_entity * dfu,u64 * size)21215970d87SPatrick Delaunay int dfu_get_medium_size_mmc(struct dfu_entity *dfu, u64 *size)
2130e285b50SStephen Warren {
2140e285b50SStephen Warren int ret;
2150e285b50SStephen Warren
2160e285b50SStephen Warren switch (dfu->layout) {
2170e285b50SStephen Warren case DFU_RAW_ADDR:
2184de51201SPatrick Delaunay *size = dfu->data.mmc.lba_size * dfu->data.mmc.lba_blk_size;
2194de51201SPatrick Delaunay return 0;
2200e285b50SStephen Warren case DFU_FS_FAT:
2210e285b50SStephen Warren case DFU_FS_EXT4:
222411c5e57SStephen Warren dfu_file_buf_filled = -1;
2234de51201SPatrick Delaunay ret = mmc_file_op(DFU_OP_SIZE, dfu, NULL, size);
2240e285b50SStephen Warren if (ret < 0)
2250e285b50SStephen Warren return ret;
2264de51201SPatrick Delaunay if (*size > CONFIG_SYS_DFU_MAX_FILE_SIZE)
227411c5e57SStephen Warren return -1;
2284de51201SPatrick Delaunay return 0;
2290e285b50SStephen Warren default:
2300e285b50SStephen Warren printf("%s: Layout (%s) not (yet) supported!\n", __func__,
2310e285b50SStephen Warren dfu_get_layout(dfu->layout));
2320e285b50SStephen Warren return -1;
2330e285b50SStephen Warren }
2340e285b50SStephen Warren }
2350e285b50SStephen Warren
mmc_file_unbuffer(struct dfu_entity * dfu,u64 offset,void * buf,long * len)236411c5e57SStephen Warren static int mmc_file_unbuffer(struct dfu_entity *dfu, u64 offset, void *buf,
237411c5e57SStephen Warren long *len)
238411c5e57SStephen Warren {
239411c5e57SStephen Warren int ret;
24015970d87SPatrick Delaunay u64 file_len;
241411c5e57SStephen Warren
242411c5e57SStephen Warren if (dfu_file_buf_filled == -1) {
243411c5e57SStephen Warren ret = mmc_file_op(DFU_OP_READ, dfu, dfu_file_buf, &file_len);
244411c5e57SStephen Warren if (ret < 0)
245411c5e57SStephen Warren return ret;
246411c5e57SStephen Warren dfu_file_buf_filled = file_len;
247411c5e57SStephen Warren }
248411c5e57SStephen Warren if (offset + *len > dfu_file_buf_filled)
249411c5e57SStephen Warren return -EINVAL;
250411c5e57SStephen Warren
251411c5e57SStephen Warren /* Add to the current buffer. */
252411c5e57SStephen Warren memcpy(buf, dfu_file_buf + offset, *len);
253411c5e57SStephen Warren
254411c5e57SStephen Warren return 0;
255411c5e57SStephen Warren }
256411c5e57SStephen Warren
dfu_read_medium_mmc(struct dfu_entity * dfu,u64 offset,void * buf,long * len)257ea2453d5SPantelis Antoniou int dfu_read_medium_mmc(struct dfu_entity *dfu, u64 offset, void *buf,
258ea2453d5SPantelis Antoniou long *len)
259cb383cd2SLukasz Majewski {
260cb383cd2SLukasz Majewski int ret = -1;
261cb383cd2SLukasz Majewski
262cb383cd2SLukasz Majewski switch (dfu->layout) {
263cb383cd2SLukasz Majewski case DFU_RAW_ADDR:
264ea2453d5SPantelis Antoniou ret = mmc_block_op(DFU_OP_READ, dfu, offset, buf, len);
265cb383cd2SLukasz Majewski break;
266cb383cd2SLukasz Majewski case DFU_FS_FAT:
26743e66272SŁukasz Majewski case DFU_FS_EXT4:
268411c5e57SStephen Warren ret = mmc_file_unbuffer(dfu, offset, buf, len);
269cb383cd2SLukasz Majewski break;
270cb383cd2SLukasz Majewski default:
271cb383cd2SLukasz Majewski printf("%s: Layout (%s) not (yet) supported!\n", __func__,
272cb383cd2SLukasz Majewski dfu_get_layout(dfu->layout));
273cb383cd2SLukasz Majewski }
274cb383cd2SLukasz Majewski
275cb383cd2SLukasz Majewski return ret;
276cb383cd2SLukasz Majewski }
277cb383cd2SLukasz Majewski
dfu_free_entity_mmc(struct dfu_entity * dfu)27841ac233cSPrzemyslaw Marczak void dfu_free_entity_mmc(struct dfu_entity *dfu)
27941ac233cSPrzemyslaw Marczak {
28041ac233cSPrzemyslaw Marczak if (dfu_file_buf) {
28141ac233cSPrzemyslaw Marczak free(dfu_file_buf);
28241ac233cSPrzemyslaw Marczak dfu_file_buf = NULL;
28341ac233cSPrzemyslaw Marczak }
28441ac233cSPrzemyslaw Marczak }
28541ac233cSPrzemyslaw Marczak
286711b931fSMateusz Zalega /*
287711b931fSMateusz Zalega * @param s Parameter string containing space-separated arguments:
288711b931fSMateusz Zalega * 1st:
289711b931fSMateusz Zalega * raw (raw read/write)
290711b931fSMateusz Zalega * fat (files)
291711b931fSMateusz Zalega * ext4 (^)
292711b931fSMateusz Zalega * part (partition image)
293711b931fSMateusz Zalega * 2nd and 3rd:
294711b931fSMateusz Zalega * lba_start and lba_size, for raw write
295711b931fSMateusz Zalega * mmc_dev and mmc_part, for filesystems and part
296c8151b4aSLukasz Majewski * 4th (optional):
297c8151b4aSLukasz Majewski * mmcpart <num> (access to HW eMMC partitions)
298711b931fSMateusz Zalega */
dfu_fill_entity_mmc(struct dfu_entity * dfu,char * devstr,char * s)299dd64827eSStephen Warren int dfu_fill_entity_mmc(struct dfu_entity *dfu, char *devstr, char *s)
300cb383cd2SLukasz Majewski {
301711b931fSMateusz Zalega const char *entity_type;
302711b931fSMateusz Zalega size_t second_arg;
303711b931fSMateusz Zalega size_t third_arg;
304711b931fSMateusz Zalega
3051b6ca18bSPantelis Antoniou struct mmc *mmc;
306711b931fSMateusz Zalega
307711b931fSMateusz Zalega const char *argv[3];
308711b931fSMateusz Zalega const char **parg = argv;
309711b931fSMateusz Zalega
310dd64827eSStephen Warren dfu->data.mmc.dev_num = simple_strtoul(devstr, NULL, 10);
311dd64827eSStephen Warren
312711b931fSMateusz Zalega for (; parg < argv + sizeof(argv) / sizeof(*argv); ++parg) {
313711b931fSMateusz Zalega *parg = strsep(&s, " ");
314711b931fSMateusz Zalega if (*parg == NULL) {
315*90aa625cSMasahiro Yamada pr_err("Invalid number of arguments.\n");
316711b931fSMateusz Zalega return -ENODEV;
317711b931fSMateusz Zalega }
318711b931fSMateusz Zalega }
319711b931fSMateusz Zalega
320711b931fSMateusz Zalega entity_type = argv[0];
321b7d4259aSMateusz Zalega /*
322b7d4259aSMateusz Zalega * Base 0 means we'll accept (prefixed with 0x or 0) base 16, 8,
323b7d4259aSMateusz Zalega * with default 10.
324b7d4259aSMateusz Zalega */
325b7d4259aSMateusz Zalega second_arg = simple_strtoul(argv[1], NULL, 0);
326b7d4259aSMateusz Zalega third_arg = simple_strtoul(argv[2], NULL, 0);
327711b931fSMateusz Zalega
328dd64827eSStephen Warren mmc = find_mmc_device(dfu->data.mmc.dev_num);
329711b931fSMateusz Zalega if (mmc == NULL) {
330*90aa625cSMasahiro Yamada pr_err("Couldn't find MMC device no. %d.\n",
331dd64827eSStephen Warren dfu->data.mmc.dev_num);
332711b931fSMateusz Zalega return -ENODEV;
333711b931fSMateusz Zalega }
334711b931fSMateusz Zalega
335711b931fSMateusz Zalega if (mmc_init(mmc)) {
336*90aa625cSMasahiro Yamada pr_err("Couldn't init MMC device.\n");
337711b931fSMateusz Zalega return -ENODEV;
338711b931fSMateusz Zalega }
339711b931fSMateusz Zalega
340c8151b4aSLukasz Majewski dfu->data.mmc.hw_partition = -EINVAL;
341711b931fSMateusz Zalega if (!strcmp(entity_type, "raw")) {
342711b931fSMateusz Zalega dfu->layout = DFU_RAW_ADDR;
343711b931fSMateusz Zalega dfu->data.mmc.lba_start = second_arg;
344711b931fSMateusz Zalega dfu->data.mmc.lba_size = third_arg;
345711b931fSMateusz Zalega dfu->data.mmc.lba_blk_size = mmc->read_bl_len;
346c8151b4aSLukasz Majewski
347c8151b4aSLukasz Majewski /*
348c8151b4aSLukasz Majewski * Check for an extra entry at dfu_alt_info env variable
349c8151b4aSLukasz Majewski * specifying the mmc HW defined partition number
350c8151b4aSLukasz Majewski */
351c8151b4aSLukasz Majewski if (s)
352c8151b4aSLukasz Majewski if (!strcmp(strsep(&s, " "), "mmcpart"))
353c8151b4aSLukasz Majewski dfu->data.mmc.hw_partition =
354c8151b4aSLukasz Majewski simple_strtoul(s, NULL, 0);
355c8151b4aSLukasz Majewski
356711b931fSMateusz Zalega } else if (!strcmp(entity_type, "part")) {
3571b6ca18bSPantelis Antoniou disk_partition_t partinfo;
358797d1b9dSSimon Glass struct blk_desc *blk_dev = mmc_get_blk_desc(mmc);
359711b931fSMateusz Zalega int mmcdev = second_arg;
360711b931fSMateusz Zalega int mmcpart = third_arg;
361cb383cd2SLukasz Majewski
3623e8bd469SSimon Glass if (part_get_info(blk_dev, mmcpart, &partinfo) != 0) {
363*90aa625cSMasahiro Yamada pr_err("Couldn't find part #%d on mmc device #%d\n",
364711b931fSMateusz Zalega mmcpart, mmcdev);
3651b6ca18bSPantelis Antoniou return -ENODEV;
3661b6ca18bSPantelis Antoniou }
3671b6ca18bSPantelis Antoniou
368711b931fSMateusz Zalega dfu->layout = DFU_RAW_ADDR;
3691b6ca18bSPantelis Antoniou dfu->data.mmc.lba_start = partinfo.start;
3701b6ca18bSPantelis Antoniou dfu->data.mmc.lba_size = partinfo.size;
3711b6ca18bSPantelis Antoniou dfu->data.mmc.lba_blk_size = partinfo.blksz;
372711b931fSMateusz Zalega } else if (!strcmp(entity_type, "fat")) {
373711b931fSMateusz Zalega dfu->layout = DFU_FS_FAT;
374711b931fSMateusz Zalega } else if (!strcmp(entity_type, "ext4")) {
375711b931fSMateusz Zalega dfu->layout = DFU_FS_EXT4;
376cb383cd2SLukasz Majewski } else {
377*90aa625cSMasahiro Yamada pr_err("Memory layout (%s) not supported!\n", entity_type);
3781b6ca18bSPantelis Antoniou return -ENODEV;
379cb383cd2SLukasz Majewski }
380cb383cd2SLukasz Majewski
381711b931fSMateusz Zalega /* if it's NOT a raw write */
382711b931fSMateusz Zalega if (strcmp(entity_type, "raw")) {
383711b931fSMateusz Zalega dfu->data.mmc.dev = second_arg;
384711b931fSMateusz Zalega dfu->data.mmc.part = third_arg;
38543e66272SŁukasz Majewski }
38643e66272SŁukasz Majewski
387711b931fSMateusz Zalega dfu->dev_type = DFU_DEV_MMC;
3880e285b50SStephen Warren dfu->get_medium_size = dfu_get_medium_size_mmc;
389cb383cd2SLukasz Majewski dfu->read_medium = dfu_read_medium_mmc;
390cb383cd2SLukasz Majewski dfu->write_medium = dfu_write_medium_mmc;
391ea2453d5SPantelis Antoniou dfu->flush_medium = dfu_flush_medium_mmc;
392ea2453d5SPantelis Antoniou dfu->inited = 0;
39341ac233cSPrzemyslaw Marczak dfu->free_entity = dfu_free_entity_mmc;
39441ac233cSPrzemyslaw Marczak
39541ac233cSPrzemyslaw Marczak /* Check if file buffer is ready */
39641ac233cSPrzemyslaw Marczak if (!dfu_file_buf) {
39741ac233cSPrzemyslaw Marczak dfu_file_buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
39841ac233cSPrzemyslaw Marczak CONFIG_SYS_DFU_MAX_FILE_SIZE);
39941ac233cSPrzemyslaw Marczak if (!dfu_file_buf) {
400*90aa625cSMasahiro Yamada pr_err("Could not memalign 0x%x bytes",
40141ac233cSPrzemyslaw Marczak CONFIG_SYS_DFU_MAX_FILE_SIZE);
40241ac233cSPrzemyslaw Marczak return -ENOMEM;
40341ac233cSPrzemyslaw Marczak }
40441ac233cSPrzemyslaw Marczak }
405cb383cd2SLukasz Majewski
406cb383cd2SLukasz Majewski return 0;
407cb383cd2SLukasz Majewski }
408